天天看點

.NET的異步調用和IAsyncResult接口

1.關于委托的BeginInvoke和EndInvoke方法

.NET Framework 允許您異步調用任何方法。為此,應定義與您要調用的方法具有相同簽名的委托;公共語言運作庫會自動使用适當的簽名為該委托定義 BeginInvoke 和 EndInvoke 方法。

例如:

namespace carydemo2

{

    public class CaryAsync

    {       

        public string LongtimeOperation(int data, out int threadId)

        {

            Console.WriteLine("Long time operation begin");

            data = data + 123;

            Thread.Sleep(500);

            threadId = Thread.CurrentThread.ManagedThreadId;

            return String.Format("Data:{0}.", data.ToString());

        }

    }

    public delegate string CaryAsyncCaller(int data, out int threadId);

    public class CaryTest

    {

        private static int threadId;

        public static void Main()

        {           

            CaryAsync ca = new CaryAsync();

            CaryAsyncCaller caller = new CaryAsyncCaller(ca.LongtimeOperation);

            IAsyncResult result = caller.BeginInvoke(3000, out threadId, null, null);

            Thread.Sleep(0);

            Console.WriteLine("Main thread :{0}", Thread.CurrentThread.ManagedThreadId);

            result.AsyncWaitHandle.WaitOne();

            while (result.IsCompleted == false)

            {

                Thread.Sleep(10);

            }

            string returnValue = caller.EndInvoke(out threadId, result);

            Console.WriteLine("The caller thread: {0}, Data :\"{1}\".", threadId, returnValue);

        }     

}

調用你可以使用 BeginInvoke 傳回的 IAsyncResult 的 AsyncWaitHandle 屬性來擷取 WaitHandle。異步調用完成時會發出 WaitHandle 信号,而您可以通過調用 WaitOne 方法等待它。這樣你就可以在異步調用完成之前或之後,在通過調用 EndInvoke 檢索結果之前,還可以執行其他處理。 

可以使用由 BeginInvoke 傳回的 IAsyncResult 的 IsCompleted 屬性來發現異步調用何時完成。 

還可以在調用完成時執行回調方法,代碼如下:

        {           

            IAsyncResult result = caller.BeginInvoke(3000, out threadId, new AsyncCallback(CaryCallBack), caller);

            Console.ReadLine();

        static void CaryCallBack(IAsyncResult ar)

            CaryAsyncCaller caller = (CaryAsyncCaller)ar.AsyncState;

            string returnValue = caller.EndInvoke(out threadId, ar);

            Console.WriteLine("The caller thread:{0},return value\"{1}\"", threadId, returnValue);

2.IAsyncResult接口:它表示異步操作的狀态.該接口定義了4個公用屬性,如下:

   AsyncState  擷取使用者定義的對象,它限定或包含關于異步操作的資訊。

   AsyncWaitHandle  擷取用于等待異步操作完成的 WaitHandle。

   CompletedSynchronously  擷取異步操作是否同步完成的訓示。

   IsCompleted  擷取異步操作是否已完成的訓示。 

IAsyncResult 接口由包含可異步操作的方法的類實作。它是啟動異步操作的方法的傳回類型,如 FileStream.BeginRead,也是結束異步操作的方法的第三個參數的類型,如 FileStream.EndRead。當異步操作完成時,IAsyncResult 對象也将傳遞給由 AsyncCallback 委托調用的方法。 

支援 IAsyncResult 接口的對象存儲異步操作的狀态資訊,并提供同步對象以允許線程在操作完成時終止。 

3. AsyncCallback 委托      

引用在異步操作完成時調用的回調方法。AsyncCallback 引用的事件處理程式包含完成用戶端異步任務的程式邏輯。AsyncCallback 使用 IAsyncResult 接口擷取異步操作的狀态。

下面為例子:

namespace carydemo1

    public class AsyncResult : System.IAsyncResult

        public object AsyncState

            get; set;

        System.Threading.WaitHandle asyncWaitHandle = new AutoResetEvent(false);

        public System.Threading.WaitHandle AsyncWaitHandle

            get { return asyncWaitHandle; }

        public bool CompletedSynchronously

        public bool IsCompleted

            get;

            set;

        public int Data

            set;get;

    class TestClass

        AsyncCallback asyncCallback;

        AsyncResult asyncResult;

        public TestClass()

            asyncCallback = new AsyncCallback(callback);

            asyncResult = new AsyncResult();

        void callback(IAsyncResult asyncResult)

            AsyncResult temp = asyncResult as AsyncResult;

            ((AutoResetEvent)temp.AsyncWaitHandle).Set();

        public AsyncResult AsyncMethod(int value, object asyncState)

            Console.WriteLine("Start...");

            this.asyncResult.AsyncState = asyncState;

            this.asyncResult.Data = value;

            Thread t = new Thread(new ThreadStart(myThread));

            t.Start();

            return this.asyncResult;

        }

        void myThread()

            Console.WriteLine("begin ");

            for (int i = 0; i < 3; i++)

                Console.WriteLine(i);

                asyncResult.Data = asyncResult.Data + i;

                Thread.Sleep(500);

            Console.WriteLine("end...");

            asyncCallback(this.asyncResult);

    class Program

        static void Main(string[] args)

            TestClass obj = new TestClass();

            AsyncResult r = obj.AsyncMethod(50, null);

            r.AsyncWaitHandle.WaitOne();

            System.Console.WriteLine(r.Data);

            System.Console.WriteLine("完成");

            System.Console.Read();

繼續閱讀