程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 用代理類包裝異步調用方法實現異步命令

用代理類包裝異步調用方法實現異步命令

編輯:C#入門知識

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>
        /// 原始調用對象www.2cto.com
        /// </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);
        }

    }
 


摘自 Kiminozo's Tech Blog

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