C#異步調用四大方法詳解
C#異步調用四大方法是什麼呢?他們各自的作用是什麼呢?那麼本文就向你介紹C#異步調用四大方法的具體內容。
C#異步調用四大方法是什麼呢?C#異步調用四大方法的使用是如何進行的呢?讓我們首先了解下什麼時候用到C#異步調用:
.NET Framework 允許您C#異步調用任何方法。定義與您需要調用的方法具有相同簽名的委託;公共語言運行庫將自動爲該委託定義具有適當簽名的 BeginInvoke 和 EndInvoke 方法。
BeginInvoke 方法用於啓動C#異步調用。它與您需要異步執行的方法具有相同的參數,只不過還有兩個額外的參數(將在稍後描述)。BeginInvoke 立即返回,不等待C#異步調用完成。BeginInvoke 返回 IasyncResult,可用於監視調用進度。
EndInvoke 方法用於檢索C#異步調用結果。調用 BeginInvoke 後可隨時調用 EndInvoke 方法;如果C#異步調用未完成,EndInvoke 將一直阻塞到C#異步調用完成。EndInvoke 的參數包括您需要異步執行的方法的 out 和 ref 參數(在 Visual Basic 中爲 ByRef 和 ByRef)以及由 BeginInvoke 返回的 IAsyncResult。
注意 Visual Studio .NET 中的智能感知功能會顯示 BeginInvoke 和 EndInvoke 的參數。如果您沒有使用 Visual Studio 或類似的工具,或者您使用的是 C# 和 Visual Studio .NET,請參見異步方法簽名獲取有關運行庫爲這些方法定義的參數的描述。
本主題中的代碼演示了四種使用 BeginInvoke 和 EndInvoke 進行C#異步調用的常用方法。調用了 BeginInvoke 後,可以:
· 進行某些操作,然後調用 EndInvoke 一直阻塞到調用完成。
· 使用 IAsyncResult.AsyncWaitHandle 獲取 WaitHandle,使用它的 WaitOne 方法將執行一直阻塞到發出 WaitHandle 信號,然後調用 EndInvoke。
· 輪詢由 BeginInvoke 返回的 IAsyncResult,確定C#異步調用何時完成,然後調用 EndInvoke。
· 將用於回調方法的委託傳遞給 BeginInvoke。該方法在C#異步調用完成後在 ThreadPool 線程上執行,它可以調用 EndInvoke。
警告:始終在C#異步調用完成後調用 EndInvoke。
測試方法和異步委託
四個示例全部使用同一個長期運行的測試方法 TestMethod。該方法顯示一個表明它已開始處理的控制檯信息,休眠幾秒鐘,然後結束。TestMethod 有一個 out 參數(在 Visual Basic 中爲 ByRef),它演示瞭如何將這些參數添加到 BeginInvoke 和 EndInvoke 的簽名中。您可以用類似的方式處理 ref 參數(在 Visual Basic 中爲 ByRef)。
下面的代碼示例顯示 TestMethod 以及代表 TestMethod 的委託;若要使用任一示例,請將示例代碼追加到這段代碼中。
注意 爲了簡化這些示例,TestMethod 在獨立於 Main() 的類中聲明。或者,TestMethod 可以是包含 Main() 的同一類中的 static 方法(在 Visual Basic 中爲 Shared)。
- using System;
- using System.Threading;
- public class AsyncDemo {
- // The method to be executed asynchronously.
- //
- public string TestMethod(
- int callDuration, out int threadId) {
- Console.WriteLine("Test method begins.");
- Thread.Sleep(callDuration);
- threadId = AppDomain.GetCurrentThreadId();
- return "MyCallTime was " + callDuration.ToString();
- }
- }
- // The delegate must have the same signature as the method
- // you want to call asynchronously.
- public delegate string AsyncDelegate(
- int callDuration, out int threadId);
- using System;
- using System.Threading;
- public class AsyncDemo {
- // The method to be executed asynchronously.
- //
- public string TestMethod(
- int callDuration, out int threadId) {
- Console.WriteLine("Test method begins.");
- Thread.Sleep(callDuration);
- threadId = AppDomain.GetCurrentThreadId();
- return "MyCallTime was " + callDuration.ToString();
- }
- }
- // The delegate must have the same signature as the method
- // you want to call asynchronously.
- public delegate string AsyncDelegate(
- int callDuration, out int threadId);
C#異步調用四大方法之使用 EndInvoke 等待異步調用
異步執行方法的最簡單方式是以 BeginInvoke 開始,對主線程執行一些操作,然後調用 EndInvoke。EndInvoke 直到C#異步調用完成後才返回。這種技術非常適合文件或網絡操作,但是由於它阻塞 EndInvoke,所以不要從用戶界面的服務線程中使用它。
- public class AsyncMain {
- static void Main(string[] args) {
- // The asynchronous method puts the thread id here.
- int threadId;
- // Create an instance of the test class.
- AsyncDemo ad = new AsyncDemo();
- // Create the delegate.
- AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);
- // Initiate the asychronous call.
- IAsyncResult ar = dlgt.BeginInvoke(3000,
- out threadId, null, null);
- Thread.Sleep(0);
- Console.WriteLine("Main thread {0} does some work.",
- AppDomain.GetCurrentThreadId());
- // Call EndInvoke to Wait for
- //the asynchronous call to complete,
- // and to retrieve the results.
- string ret = dlgt.EndInvoke(out threadId, ar);
- Console.WriteLine("The call executed on thread {0},
- with return value \"{1}\".", threadId, ret);
- }
- }
C#異步調用四大方法之使用 WaitHandle 等待異步調用
等待 WaitHandle 是一項常用的線程同步技術。您可以使用由 BeginInvoke 返回的 IAsyncResult 的 AsyncWaitHandle 屬性來獲取 WaitHandle。C#異步調用完成時會發出 WaitHandle 信號,而您可以通過調用它的 WaitOne 等待它。
如果您使用 WaitHandle,則在C#異步調用完成之後,但在通過調用 EndInvoke 檢索結果之前,可以執行其他處理。
- public class AsyncMain {
- static void Main(string[] args) {
- // The asynchronous method puts the thread id here.
- int threadId;
- // Create an instance of the test class.
- AsyncDemo ad = new AsyncDemo();
- // Create the delegate.
- AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);
- // Initiate the asychronous call.
- IAsyncResult ar = dlgt.BeginInvoke(3000,
- out threadId, null, null);
- Thread.Sleep(0);
- Console.WriteLine("Main thread {0} does some work.",
- AppDomain.GetCurrentThreadId());
- // Wait for the WaitHandle to become signaled.
- ar.AsyncWaitHandle.WaitOne();
- // Perform additional processing here.
- // Call EndInvoke to retrieve the results.
- string ret = dlgt.EndInvoke(out threadId, ar);
- Console.WriteLine("The call executed on thread {0},
- with return value \"{1}\".", threadId, ret);
- }
- }
C#異步調用四大方法之輪詢異步調用完成
您可以使用由 BeginInvoke 返回的 IAsyncResult 的 IsCompleted 屬性來發現C#異步調用何時完成。從用戶界面的服務線程中進行C#異步調用時可以執行此操作。輪詢完成允許用戶界面線程繼續處理用戶輸入。
- public class AsyncMain {
- static void Main(string[] args) {
- // The asynchronous method puts the thread id here.
- int threadId;
- // Create an instance of the test class.
- AsyncDemo ad = new AsyncDemo();
- // Create the delegate.
- AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);
- // Initiate the asychronous call.
- IAsyncResult ar = dlgt.BeginInvoke(3000,
- out threadId, null, null);
- // Poll while simulating work.
- while(ar.IsCompleted == false) {
- Thread.Sleep(10);
- }
- // Call EndInvoke to retrieve the results.
- string ret = dlgt.EndInvoke(out threadId, ar);
- Console.WriteLine("The call executed on thread {0},
- with return value \"{1}\".", threadId, ret);
- }
- }
C#異步調用四大方法之異步調用完成時執行回調方法
如果啓動異步調用的線程不需要處理調用結果,則可以在調用完成時執行回調方法。回調方法在 ThreadPool 線程上執行。
要使用回調方法,必須將代表該方法的 AsyncCallback 委託傳遞給 BeginInvoke。也可以傳遞包含回調方法將要使用的信息的對象。例如,可以傳遞啓動調用時曾使用的委託,以便回調方法能夠調用 EndInvoke。
- public class AsyncMain {
- // Asynchronous method puts the thread id here.
- private static int threadId;
- static void Main(string[] args) {
- // Create an instance of the test class.
- AsyncDemo ad = new AsyncDemo();
- // Create the delegate.
- AsyncDelegate dlgt = new AsyncDelegate(ad.TestMethod);
- // Initiate the asychronous call. Include an AsyncCallback
- // delegate representing the callback method, and the data
- // needed to call EndInvoke.
- IAsyncResult ar = dlgt.BeginInvoke(3000,
- out threadId,
- new AsyncCallback(CallbackMethod),
- dlgt );
- Console.WriteLine("Press Enter to close application.");
- Console.ReadLine();
- }
- // Callback method must have the same signature as the
- // AsyncCallback delegate.
- static void CallbackMethod(IAsyncResult ar) {
- // Retrieve the delegate.
- AsyncDelegate dlgt = (AsyncDelegate) ar.AsyncState;
- // Call EndInvoke to retrieve the results.
- string ret = dlgt.EndInvoke(out threadId, ar);
- Console.WriteLine("The call executed on thread {0},
- with return value \"{1}\".", threadId, ret);
- }
- }
原文地址:http://developer.51cto.com/art/200908/145541.htm