簡略完成C#異步操作。本站提示廣大學習愛好者:(簡略完成C#異步操作)文章只能為提供參考,不一定能成為您想要的結果。以下是簡略完成C#異步操作正文
在.net4.0今後異步操作,並行盤算變得異常簡略,然則因為公司項目開辟基於.net3.5所以沒法用到4.0的並行盤算和Task等異步編程。是以,為了今後更便利的停止異步方法的開辟,我封裝完成了異步編程框架,經由過程BeginInvoke、EndInvoke的方法完成異步編程。
1、框架構造
全部框架包含四個部門
1、基類籠統Opeartor
我把每一個異步履行進程稱為一個Operate,是以須要一個Opeartor去履行
2、FuncAsync
異步的Func
3、ActionAsync
異步的Action
4、Asynchorus
對ActionAsync和FuncAsync的封裝
Operator
Operator是一個籠統類,完成了IOperationAsync和IContinueWithAsync兩個接口。
IOperationAsync完成了異步操作,IContinueWithAsync完成了相似於Task的ContinueWith辦法,在以後異步操作完成後持續停止的操作
IOperationAsync接口詳解
public interface IOperationAsync { IAsyncResult Invoke(); void Wait(); void CompletedCallBack(IAsyncResult ar); void CatchException(Exception exception); }
IContinueWithAsync接口概況
public interface IContinueWithAsync { Operator Previous { get; set; } Operator Next { get; set; } Operator ContinueWithAsync(Action action); Operator ContinueWithAsync<TParameter>(Action<TParameter> action, TParameter parameter); }
Previous:前一個操作
Next:下一個操作
ContinueWithAsync():異步持續操作
public abstract class Operator : IOperationAsync, IContinueWithAsync { public IAsyncResult Middle; public readonly string Id; public Exception Exception { get; private set; } public Operator Previous { get; set; } public Operator Next { get; set; } protected Operator() { Id = Guid.NewGuid().ToString(); } public abstract IAsyncResult Invoke(); protected void SetAsyncResult(IAsyncResult result) { this.Middle = result; } public virtual void Wait() { if (!Middle.IsCompleted) Middle.AsyncWaitHandle.WaitOne(); } public virtual void CompletedCallBack(IAsyncResult ar) { } public void CatchException(Exception exception) { this.Exception = exception; } protected Operator ContinueAsync() { if (Next != null) Next.Invoke(); return Next; } public virtual Operator ContinueWithAsync(Action action) { Next = new ActionAsync(action); Next.Previous = this; return Next; } public virtual Operator ContinueWithAsync<TParameter>(Action<TParameter> action, TParameter parameter) { Next = new ActionAsync<TParameter>(action, parameter); Next.Previous = this; return Next; } public virtual Operator ContinueWithAsync<TResult>(Func<TResult> func) { Next = new FuncAsync<TResult>(); Next.Previous = this; return Next; } public virtual Operator ContinueWithAsync<TParameter, TResult>(Func<TParameter, TResult> func, TParameter parameter) { Next = new FuncAsync<TParameter, TResult>(func, parameter); Next.Previous = this; return Next; } }
無前往異步操作
ActionAsync
public class ActionAsync : Operator { private readonly Action _action; protected ActionAsync() { } public ActionAsync(Action action) : this() { this._action = action; } public override IAsyncResult Invoke() { var middle = _action.BeginInvoke(CompletedCallBack, null); SetAsyncResult(middle); return middle; } public override void CompletedCallBack(IAsyncResult ar) { try { _action.EndInvoke(ar); } catch (Exception exception) { this.CatchException(exception); } ContinueAsync(); } } public class ActionAsync<T> : ActionAsync { public T Result; private readonly Action<T> _action1; protected readonly T Parameter1; public ActionAsync() { } public ActionAsync(T parameter) { this.Parameter1 = parameter; } public ActionAsync(Action<T> action, T parameter) { this._action1 = action; this.Parameter1 = parameter; } public override IAsyncResult Invoke() { var result = _action1.BeginInvoke(Parameter1, CompletedCallBack, null); SetAsyncResult(result); return result; } public override void CompletedCallBack(IAsyncResult ar) { try { _action1.EndInvoke(ar); } catch (Exception exception) { this.CatchException(exception); } ContinueAsync(); } }
有前往異步
FuncAsync完成了IFuncOperationAsync接口
IFuncOperationAsync
public interface IFuncOperationAsync<T> { void SetResult(T result); T GetResult(); }
1)、FuncAsync
public class FuncAsync<TResult> : Operator, IFuncOperationAsync<TResult> { private TResult _result; public TResult Result { get { if (!Middle.IsCompleted || _result == null) { _result = GetResult(); } return _result; } } private readonly Func<TResult> _func1; public FuncAsync() { } public FuncAsync(Func<TResult> func) { this._func1 = func; } public override IAsyncResult Invoke() { var result = _func1.BeginInvoke(CompletedCallBack, null); SetAsyncResult(result); return result; } public override void CompletedCallBack(IAsyncResult ar) { try { var result = _func1.EndInvoke(ar); SetResult(result); } catch (Exception exception) { this.CatchException(exception); SetResult(default(TResult)); } ContinueAsync(); } public virtual TResult GetResult() { Wait(); return this._result; } public void SetResult(TResult result) { _result = result; } } public class FuncAsync<T1, TResult> : FuncAsync<TResult> { protected readonly T1 Parameter1; private readonly Func<T1, TResult> _func2; public FuncAsync(Func<T1, TResult> action, T1 parameter1) : this(parameter1) { this._func2 = action; } protected FuncAsync(T1 parameter1) : base() { this.Parameter1 = parameter1; } public override IAsyncResult Invoke() { var result = _func2.BeginInvoke(Parameter1, CompletedCallBack, null); SetAsyncResult(result); return result; } public override void CompletedCallBack(IAsyncResult ar) { try { var result = _func2.EndInvoke(ar); SetResult(result); } catch (Exception exception) { CatchException(exception); SetResult(default(TResult)); } ContinueAsync(); } }
Asynchronous 異步操作封裝
ActionAsync和FuncAsync為異步操作打下了基本,接上去最主要的任務就是經由過程這兩個類履行我們的異步操作,為此我封裝了一個異步操作類
重要封裝了以下幾個部門:
前面四個包括若干個重載,這裡只是籠統的代表一個類型的辦法
WaitAll
public static void WaitAll(IEnumerable<Operator> operations) { foreach (var @operator in operations) { @operator.Wait(); } }
WaitAny
public static void WaitAny(IEnumerable<Operator> operations) { while (operations.All(o => !o.Middle.IsCompleted)) Thread.Sleep(100); }
期待時光可以自界說
ActionInvoke
public static Operator Invoke(Action action) { Operator operation = new ActionAsync(action); operation.Invoke(); return operation; } public static Operator Invoke<T>(Action<T> action, T parameter) { Operator operation = new ActionAsync<T>(action, parameter); operation.Invoke(); return operation; } public static Operator Invoke<T1, T2>(Action<T1, T2> action, T1 parameter1, T2 parameter2) { Operator operation = new ActionAsync<T1, T2>(action, parameter1, parameter2); operation.Invoke(); return operation; }
FuncInvoke
public static Operator Invoke<TResult>(Func<TResult> func) { Operator operation = new FuncAsync<TResult>(func); operation.Invoke(); return operation; } public static Operator Invoke<TParameter, TResult>(Func<TParameter, TResult> func, TParameter parameter) { TParameter param = parameter; Operator operation = new FuncAsync<TParameter, TResult>(func, param); operation.Invoke(); return operation; } public static Operator Invoke<T1, T2, TResult>(Func<T1, T2, TResult> func, T1 parameter1, T2 parameter2) { Operator operation = new FuncAsync<T1, T2, TResult>(func, parameter1, parameter2); operation.Invoke(); return operation; }
ContinueWithAction
public static Operator ContinueWithAsync(IEnumerable<Operator>operators, Action action) { return Invoke(WaitAll, operators) .ContinueWithAsync(action); } public static Operator ContinueWithAsync<TParameter>(IEnumerable<Operator> operators, Action<TParameter> action, TParameter parameter) { return Invoke(WaitAll, operators) .ContinueWithAsync(action, parameter); }
ContinueWithFunc
public static Operator ContinueWithAsync<TResult>(IEnumerable<Operator> operators,Func<TResult> func) { return Invoke(WaitAll, operators) .ContinueWithAsync(func); } public static Operator ContinueWithAsync<TParameter, TResult>(IEnumerable<Operator> operators, Func<TParameter, TResult> func, TParameter parameter) { return Invoke(WaitAll, operators) .ContinueWithAsync(func, parameter); }
這裡有個bug當挪用ContinueWithAsync後沒法挪用Wait期待,原來Wait須要早年往後期待每一個異步操作,然則測試了下不相符預期成果。不外實際下去說應當無需如許操作,ContinueWithAsync只是為了當上一個異步操作履行終了時持續履行的異步操作,若要期待,那不如兩個操作放到一路,最初再期待仍然可以完成。
後面的都是單步異步操作的挪用,若須要對某聚集停止某個辦法的異步操作,可以foreach遍歷
public void ForeachAsync(IEnumerbale<string> parameters) { foreach(string p in parameters) { Asynchronous.Invoke(Tast,p); } } public void Test(string parameter) { //TODO:做一些事 }
每次都須要去手寫foreach,比擬費事,是以完成相似於PLinq的並行盤算辦法其實有需要,不外有一點差異,PLinq是采取多核CPU停止並行盤算,而我封裝的僅僅遍歷聚集停止異步操作罷了
ForeachAction
public static IEnumerable<Operator> Foreach<TParameter>(IEnumerable<TParameter> items, Action<TParameter> action) { return items.Select(t => Invoke(action, t)).ToList(); }
ForeachFunc
public static IEnumerable<Operator> Foreach<TParameter, TResult>(IEnumerable<TParameter> items, Func<TParameter, TResult> func) { return items.Select(parameter => Invoke(func, parameter)).ToList(); }
若何應用
無前往值異步辦法挪用
public void DoSomeThing() { //TODO: }
經由過程Asynchronous.Invoke(DoSomeThing) 履行
public void DoSomeThing(string parameter) { //TODO: }
經由過程Asynchronous.Invoke(DoSomeThing,parameter) 履行
有前往值異步辦法挪用
public string DoSomeThing() { //TODO: }
經由過程Asynchronous.Invoke(()=>DoSomeThing())履行
public string DoSomeThing(string parameter) { //TODO: }
經由過程Asynchronous.Invoke(()=>DoSomeThing(parameter))履行,或許也能夠傳入參數經由過程Asynchronous.Invoke(p=>DoSomeThing(p),parameter)
無前往值Foreach
public void Test { int[] parameters = {1,2,3,4,5}; Asynchronous.Foreach(parameters,Console.WriteLine); }
有前往值Foreach
public void Test { int[] parameters = {1,2,3,4,5}; var operators = Asynchronous.Foreach(parameters,p=> p*2); Asynchrous.WaitAll(operators); Asynchronous.Foreach(operators.Cast<FuncAsync<int,int>>(), p=> Console.WriteLine(p.Result)); }
起首將聚集每一個值擴展2倍,然後輸入
異步履行完再履行
public void Test { int[] parameters = {1,2,3,4,5}; var operators = Asynchronous.Foreach(parameters,p=> p*2); Asynchrous.ContinueWithAsync(operators,Console.WriteLine,"履行完成"); }
每次履行完持續履行
能夠有時刻我們須要遍歷一個聚集,每一個元素處置完成後我們須要輸入XX處置完成
public void Test { int[] parameters = {1,2,3,4,5}; var operators = Asynchronous.Foreach(parameters,p=> p*2); Asynchronous.Foreach(operators,o=>{ o.ContinueWithAsync(()={ //每一個元素履行完時履行 if(o.Exception != null) { //之前履行時發生未處置的異常,這裡可以捕捉到 } }); }); }
可以完成鏈式異步操作
public void Chain() { Asynchronous.Invoke(Console.WriteLine,1) .ContinueWithAsync(Console.WriteLine,2) .ContinueWithAsync(Console.WriteLine,3) }
如許會按步調輸入1,2,3
停止語
以上只是列出了部門重載辦法,其他重載辦法不過就是加參數,實質現實是一樣的。
願望對年夜家的進修有所贊助,在這祝年夜家新年快活,新的一年年夜家一路盡力。