当前位置:编程学习 > C#/ASP.NET >>

用代理类包装异步调用方法实现异步命令

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);
        }

    } --------------------编程问答-------------------- 分享是好事,不过建议你发到博客上去。论坛里一会就沉了,也不方便其他朋友集中阅读。
补充:.NET技术 ,  非技术区
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,