(查詢BeginInvoke 2005MSDN 裏相關資料,我複製在這裏)
.NET Framework 允許您異步調用任何方法。爲此,應定義與您要調用的方法具有相同簽名的委託;公共語言運行庫會自動使用適當的簽名爲該委託定義 BeginInvoke 和 EndInvoke 方法。
BeginInvoke 方法可啓動異步調用。它與您需要異步執行的方法具有相同的參數,另外它還有兩個可選參數。第一個參數是一個 AsyncCallback 委託,該委託引用在異步調用完成時要調用的方法。第二個參數是一個用戶定義的對象,該對象可向回調方法傳遞信息。BeginInvoke 立即返回,不等待異步調用完成。BeginInvoke 會返回 IAsyncResult,這個結果可用於監視異步調用進度。
EndInvoke 方法檢索異步調用的結果。調用 BeginInvoke 後可隨時調用 EndInvoke 方法;如果異步調用尚未完成,EndInvoke 將一直阻止調用線程,直到異步調用完成後才允許調用線程執行。EndInvoke 的參數包括您需要異步執行的方法的 out 和 ref 參數(在 Visual Basic 中爲 <Out> ByRef 和 ByRef)以及由 BeginInvoke 返回的 IAsyncResult。
本主題中的代碼示例演示了四種使用 BeginInvoke 和 EndInvoke 進行異步調用的常用方法。調用 BeginInvoke 之後,您可以執行下列操作:
-
進行某些操作,然後調用 EndInvoke 一直阻止到調用完成。
-
使用 System.IAsyncResult.AsyncWaitHandle 屬性獲取 WaitHandle,使用它的 WaitOne 方法一直阻止執行直到發出 WaitHandle 信號,然後調用 EndInvoke。
-
輪詢由 BeginInvoke 返回的 IAsyncResult,確定異步調用何時完成,然後調用 EndInvoke。
-
將用於回調方法的委託傳遞給 BeginInvoke。異步調用完成後,將在 ThreadPool 線程上執行該方法。該回調方法將調用 EndInvoke。
每次都要調用 EndInvoke 來完成異步調用。
定義測試方法和異步委託
下面的代碼示例演示異步調用同一個長時間運行的方法 TestMethod
的各種方式。TestMethod
方法會顯示一條控制檯消息,說明它已開始處理,休眠了幾秒鐘,然後結束。TestMethod
有一個 out
參數,該參數用於演示此種參數添加到 BeginInvoke 和 EndInvoke 的簽名中的方式。您可以按同樣的方式處理 ref 參數。
下面的代碼示例演示 TestMethod
的定義和名爲 AsyncMethodCaller
的、可用來異步調用 TestMethod
的委託。若要編譯任何代碼示例,必須包括 TestMethod
的定義和 AsyncMethodCaller
委託。
I |
C# | |
---|---|
using System; using System.Threading; namespace Examples.AdvancedProgramming.AsynchronousOperations { 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 = Thread.CurrentThread.ManagedThreadId; return String.Format("My call time was {0}.", callDuration.ToString()); } } // The delegate must have the same signature as the method // it will call asynchronously. public delegate string AsyncMethodCaller(int callDuration, out int threadId); } |
使用 EndInvoke 等待異步調用
異步執行方法最簡單的方式是通過調用委託的 BeginInvoke 方法來開始執行方法,在主線程上執行一些工作,然後調用委託的 EndInvoke 方法。EndInvoke 可能會阻止調用線程,因爲它直到異步調用完成之後才返回。這種技術非常適合文件或網絡操作,但是由於 EndInvoke 會阻止它,所以不要從服務於用戶界面的線程中調用它。
C# | |
---|---|
using System; using System.Threading; namespace Examples.AdvancedProgramming.AsynchronousOperations { public class AsyncMain { public static void Main() { // The asynchronous method puts the thread id here. int threadId; // Create an instance of the test class. AsyncDemo ad = new AsyncDemo(); // Create the delegate. AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod); // Initiate the asychronous call. IAsyncResult result = caller.BeginInvoke(3000, out threadId, null, null); Thread.Sleep(0); Console.WriteLine("Main thread {0} does some work.", Thread.CurrentThread.ManagedThreadId); // Call EndInvoke to wait for the asynchronous call to complete, // and to retrieve the results. string returnValue = caller.EndInvoke(out threadId, result); Console.WriteLine("The call executed on thread {0}, with return value /"{1}/".", threadId, returnValue); } } } |
使用 WaitHandle 等待異步調用
您可以使用 BeginInvoke 返回的 IAsyncResult 的 AsyncWaitHandle 屬性來獲取 WaitHandle。異步調用完成時會發出 WaitHandle 信號,而您可以通過調用 WaitOne 方法等待它。
如果您使用 WaitHandle,則在異步調用完成之前或之後,在通過調用 EndInvoke 檢索結果之前,還可以執行其他處理。
C# | |
---|---|
using System; using System.Threading; namespace Examples.AdvancedProgramming.AsynchronousOperations { public class AsyncMain { static void Main() { // The asynchronous method puts the thread id here. int threadId; // Create an instance of the test class. AsyncDemo ad = new AsyncDemo(); // Create the delegate. AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod); // Initiate the asychronous call. IAsyncResult result = caller.BeginInvoke(3000, out threadId, null, null); Thread.Sleep(0); Console.WriteLine("Main thread {0} does some work.", Thread.CurrentThread.ManagedThreadId); // Wait for the WaitHandle to become signaled. result.AsyncWaitHandle.WaitOne(); // Perform additional processing here. // Call EndInvoke to retrieve the results. string returnValue = caller.EndInvoke(out threadId, result); Console.WriteLine("The call executed on thread {0}, with return value /"{1}/".", threadId, returnValue); } } } |
輪詢異步調用完成
您可以使用由 BeginInvoke 返回的 IAsyncResult 的 IsCompleted 屬性來發現異步調用何時完成。從用戶界面的服務線程中進行異步調用時可以執行此操作。輪詢完成允許調用線程在異步調用在 ThreadPool 線程上執行時繼續執行。
C# | |
---|---|
using System; using System.Threading; namespace Examples.AdvancedProgramming.AsynchronousOperations { public class AsyncMain { static void Main() { // The asynchronous method puts the thread id here. int threadId; // Create an instance of the test class. AsyncDemo ad = new AsyncDemo(); // Create the delegate. AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod); // Initiate the asychronous call. IAsyncResult result = caller.BeginInvoke(3000, out threadId, null, null); // Poll while simulating work. while(result.IsCompleted == false) { Thread.Sleep(10); } // Call EndInvoke to retrieve the results. string returnValue = caller.EndInvoke(out threadId, result); Console.WriteLine("The call executed on thread {0}, with return value /"{1}/".", threadId, returnValue); } } } |
異步調用完成時執行回調方法
如果啓動異步調用的線程不需要是處理結果的線程,則可以在調用完成時執行回調方法。回調方法在 ThreadPool 線程上執行。
若要使用回調方法,必須將引用回調方法的 AsyncCallback 委託傳遞給 BeginInvoke。也可以傳遞包含回調方法將要使用的信息的對象。例如,可以傳遞啓動調用時曾使用的委託,以便回調方法能夠調用 EndInvoke。
C# | |
---|---|
using System; using System.Threading; namespace Examples.AdvancedProgramming.AsynchronousOperations { public class AsyncMain { // Asynchronous method puts the thread id here. private static int threadId; static void Main() { // Create an instance of the test class. AsyncDemo ad = new AsyncDemo(); // Create the delegate. AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod); // Initiate the asychronous call. Include an AsyncCallback // delegate representing the callback method, and the data // needed to call EndInvoke. IAsyncResult result = caller.BeginInvoke(3000, out threadId, new AsyncCallback(CallbackMethod), caller ); 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. AsyncMethodCaller caller = (AsyncMethodCaller) ar.AsyncState; // Call EndInvoke to retrieve the results. string returnValue = caller.EndInvoke(out threadId, ar); Console.WriteLine("The call executed on thread {0}, with return value /"{1}/".", threadId, returnValue); } } } |