程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 簡略完成C#異步操作

簡略完成C#異步操作

編輯:C#入門知識

簡略完成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);
}
  • Invoke():異步辦法的挪用
  • Wait():期待異步操作履行
  • CompletedCallBack():操作完成回調
  • CatchException():抓取異常

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();
}
  • SetResult(T result):異步操作完成設置前往值
  • 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(IEnumerable<Operator> operations):期待一切操作履行終了
  • WaitAny(IEnumerable<Operator> operations):期待隨意率性操作履行終了
  • ActionAsync
  • FuncAsync
  • ContinueWithAction
  • ContinueWithFunc

前面四個包括若干個重載,這裡只是籠統的代表一個類型的辦法
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
停止語

以上只是列出了部門重載辦法,其他重載辦法不過就是加參數,實質現實是一樣的。

願望對年夜家的進修有所贊助,在這祝年夜家新年快活,新的一年年夜家一路盡力。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved