zoukankan      html  css  js  c++  java
  • 用代理类包装异步调用方法实现异步命令

    C#开发中经常需要使用使用异步操作,特别是Windows phone和Silverlight下层的很多IO相关的访问都是异步的。
    标准异步方法一般都是Begin[Invoke]和End[Invoke]的一对方法,用法就不多说了。

    我最近在写用命令模式常用的HttpRequest操作,就想将命令包装成异步方法,
    想了很久使用了下面的方式包装异步:

    首先是常规的异步调用时序:



    现在使用包装使用了2个类一个用于包装AsyncCallback,一个用于包装IAsyncResult,来包装这个时序。
    类的代码如下:

     /// <summary>
    /// 异步回调代理
    /// </summary>
    public class AsyncCallbackDelegate
    {
    /// <summary>
    /// 需要代理的异步回调
    /// </summary>
    private readonly AsyncCallback asyncCallback;

    /// <summary>
    /// 原始调用对象
    /// </summary>
    public object Delegate { get; set; }

    public AsyncResultDelegate Result { get; set; }

    /// <summary>
    /// 构造 异步回调代理
    /// </summary>
    /// <param name="asyncCallback">需要代理的异步回调</param>
    public AsyncCallbackDelegate(AsyncCallback asyncCallback)
    {
    this.asyncCallback = asyncCallback;
    }

    /// <summary>
    /// 包装后的异步回调
    /// </summary>
    /// <param name="asyncResult"></param>
    public void AsyncCallBack(IAsyncResult asyncResult)
    {
    //用AsyncResultDelegate包装asyncResult
    var asyncResultDelegate = new AsyncResultDelegate(asyncResult) { Delegate = Delegate };
    asyncCallback(asyncResultDelegate);//调用原始异步回调
    }
    }
    /// <summary>
    /// 异步状态代理
    /// </summary>
    public class AsyncResultDelegate : IAsyncResult
    {
    /// <summary>
    /// 原始异步状态
    /// </summary>
    private readonly IAsyncResult asyncResult;

    /// <summary>
    /// 原始调用对象
    /// </summary>
    public object Delegate { get; set; }

    public AsyncResultDelegate(IAsyncResult asyncResult)
    {
    this.asyncResult = asyncResult;
    }

    #region 装饰模式包装

    public object AsyncState
    {
    get { return AsyncResult.AsyncState; }
    }

    public System.Threading.WaitHandle AsyncWaitHandle
    {
    get { return AsyncResult.AsyncWaitHandle; }
    }

    public bool CompletedSynchronously
    {
    get { return AsyncResult.CompletedSynchronously; }
    }

    public bool IsCompleted
    {
    get { return AsyncResult.IsCompleted; }
    }

    public IAsyncResult AsyncResult
    {
    get { return asyncResult; }
    }
    #endregion
    }

    包装后的调用时序:





    演示代码AddCommand 用于使用代理包装异步执行a+b返回结果

    public class AddCommand
    {
    private readonly int a;
    private readonly int b;

    public AddCommand(int a, int b)
    {
    this.a = a;
    this.b = b;
    }

    public IAsyncResult BeginInvoke(AsyncCallback asyncCallback, object state)
    {
    Func<int, int, int> addFunc = (x, y) => x + y;//测试用的原始异步调用对象

    AsyncCallback callbackDelegate = asyncCallback;
    if (asyncCallback != null)
    {
    //用AsyncCallbackDelegate包装AsyncCallback
    var tmp = new AsyncCallbackDelegate(asyncCallback) { Delegate = addFunc };
    callbackDelegate = tmp.AsyncCallBack;
    }
    var asyncResult = addFunc.BeginInvoke(a, b, callbackDelegate, state);
    //用AsyncResultDelegate包装asyncResult
    return new AsyncResultDelegate(asyncResult) { Delegate = addFunc };
    }


    public int EndInovke(IAsyncResult result)
    {
    var asyncResultDelegate = (AsyncResultDelegate)result;//还原AsyncResultDelegate
    Func<int, int, int> addFunc = (Func<int, int, int>)asyncResultDelegate.Delegate;//获得原始对象
    return addFunc.EndInvoke(asyncResultDelegate.AsyncResult);//传入原始AsyncResult
    }
    }

    调用AddCommand 支持2种调用方式

    class Program
    {
    static void Main(string[] args)
    {
    //主线程等待后调用EndInovke
    {
    AddCommand invoker = new AddCommand(1, 2);
    var async = invoker.BeginInvoke(null, null);
    async.AsyncWaitHandle.WaitOne();
    int result = invoker.EndInovke(async);
    Console.WriteLine(result);
    }

    //由CallBack调用EndInovke
    {
    AddCommand invoker = new AddCommand(5, 9);
    var async = invoker.BeginInvoke(CallBack, invoker);
    async.AsyncWaitHandle.WaitOne();
    }
    Console.ReadLine();
    }

    static void CallBack(IAsyncResult asyncResult)
    {
    AddCommand invoker = asyncResult.AsyncState as AddCommand;
    int result = invoker.EndInovke(asyncResult);
    Console.WriteLine(result);
    }

    }



    varcolor: #0000ff;

    /spanspan style=

  • 相关阅读:
    JavaScript-4.2函数,变量作用域---ShinePans
    2019-8-31-C#-简单读取文件
    2019-8-31-C#-简单读取文件
    2019-8-31-C#-大端小端转换
    2019-8-31-C#-大端小端转换
    2019-6-11-C#-标准性能测试
    2019-6-11-C#-标准性能测试
    2018-2-13-win10-uwp-右击选择-GridViewItem-
    2018-2-13-win10-uwp-右击选择-GridViewItem-
    2019-8-31-NuGet-如何设置图标
  • 原文地址:https://www.cnblogs.com/kiminozo/p/2370152.html
Copyright © 2011-2022 走看看