文章目錄
- 1.2 在當前線程中啟動線程T,然後繼續執行當前線程中的其它任務R1,等待T執行完成,當T執行完成後,繼續執行當前線程中的其它任務R2,最後擷取T的傳回值
- 1.3 在當前線程中啟動線程T,只要T在執行就執行任務R,最後擷取T的傳回值
- 2 不需要在當前線程中擷取傳回值,但是仍然需要對傳回值做處理
這幾天,看WF本質論,裡面提到了.net的非同步處理。由於裡面使用的是程式碼片段,所以有點看不懂。於是下定決心,溫習一下.net中的非同步處理。
使用C#在.net開發已經有5年了,最初使用.net中的非同步處理大約是在4年前。當時,只是為了實現要求的功能,沒有詳細研究。這也難怪看WF時會頭暈(基礎不牢的後果呀)。
首先,我們分析一下非同步處理的環境
- 需要在當前線程中擷取傳回值
- 不需要在當前線程中擷取傳回值,但是仍然需要對傳回值做處理
對於第1中情況,還可以繼續細分
- 在當前線程中啟動線程T,然後繼續執行當前線程中的其它任務,最後在當前線程中擷取T的傳回值
- 在當前線程中啟動線程T,然後繼續執行當前線程中的其它任務R1,等待T執行完成,當T執行完成後,繼續執行當前線程中的其它任務R2,最後擷取T的傳回值
- 在當前線程中啟動線程T,只要T在執行就執行任務R,最後擷取T的傳回值
下面,我將一一給出例子:
1.1 在當前線程中啟動線程T,然後繼續執行當前線程中的其它任務,最後在當前線程中擷取T的傳回值
using System;using System.Collections.Generic;using System.Linq;using System.Windows.Forms;using System.Threading;using System.Runtime.Remoting.Messaging;namespace FirstWF{ static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { AsyncFuncDelegate caller = new AsyncFuncDelegate(Func); Console.WriteLine("Input number please..."); IAsyncResult result = caller.BeginInvoke(Convert.ToInt32(Console.ReadLine()), null, null); Console.WriteLine("Implement other tasks"); Thread.Sleep(7000); Console.WriteLine("Implement other tasks end ..."); Console.WriteLine("Get user's input"); Console.WriteLine(caller.EndInvoke(result)); Console.ReadLine(); } delegate string AsyncFuncDelegate(int userInput); static string Func(int userInput) { Console.WriteLine("Func start to run"); Console.WriteLine("..."); Thread.Sleep(5000); Console.WriteLine("Func end to run"); return userInput.ToString(); } }}
輸出結果如下:
Implement other tasks
Func start to run
...
Func end to run
Implement other tasks end ...
Get user's input
56
1.2 在當前線程中啟動線程T,然後繼續執行當前線程中的其它任務R1,等待T執行完成,當T執行完成後,繼續執行當前線程中的其它任務R2,最後擷取T的傳回值
static void Main() { AsyncFuncDelegate caller = new AsyncFuncDelegate(Func); Console.WriteLine("Input number please..."); IAsyncResult result = caller.BeginInvoke(Convert.ToInt32(Console.ReadLine()), null, null); Console.WriteLine("Implement task 1"); result.AsyncWaitHandle.WaitOne(); result.AsyncWaitHandle.Close(); Console.WriteLine("Implment task 2"); Console.WriteLine("Get user's input"); Console.WriteLine(caller.EndInvoke(result)); Console.ReadLine(); }
輸出結果如下:
Input number please...
25
Implement task 1
Func start to run
...
Func end to run
Implment task 2
Get user's input
25
1.3 在當前線程中啟動線程T,只要T在執行就執行任務R,最後擷取T的傳回值
[STAThread] static void Main() { AsyncFuncDelegate caller = new AsyncFuncDelegate(Func); Console.WriteLine("Input number please..."); IAsyncResult result = caller.BeginInvoke(Convert.ToInt32(Console.ReadLine()), null, null); while (!result.IsCompleted) { Thread.Sleep(1000); Console.Write(">"); } Console.WriteLine(""); Console.WriteLine("Implement other task2"); Console.WriteLine("Get user's input"); Console.WriteLine(caller.EndInvoke(result)); Console.ReadLine(); }
輸出結果如下:
Func start to run
...
>>>>>Func end to run
>
Implement other task2
Get user's input
23
2 不需要在當前線程中擷取傳回值,但是仍然需要對傳回值做處理
using System;using System.Collections.Generic;using System.Linq;using System.Windows.Forms;using System.Threading;using System.Runtime.Remoting.Messaging;namespace FirstWF{ static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { AsyncFuncDelegate caller = new AsyncFuncDelegate(Func); Console.WriteLine("Input number please..."); caller.BeginInvoke(Convert.ToInt32(Console.ReadLine()), new AsyncCallback(CallBackFunc), "Message from Main thread."); Console.WriteLine("Main thread ends"); Console.ReadLine(); } delegate string AsyncFuncDelegate(int userInput); static string Func(int userInput) { Console.WriteLine("Func start to run"); Console.WriteLine("..."); Thread.Sleep(5000); Console.WriteLine("Func end to run"); return userInput.ToString(); } static void CallBackFunc(IAsyncResult ar) { AsyncResult result = ar as AsyncResult; string inputMessage = result.AsyncState as string; AsyncFuncDelegate caller = result.AsyncDelegate as AsyncFuncDelegate; Console.WriteLine("call back starts"); Console.WriteLine(inputMessage); Console.WriteLine("The input number is : " + caller.EndInvoke(ar)); Console.WriteLine("call back ends"); } }}
輸出結果如下:
Input number please...
23
Main thread ends
Func start to run
...
Func end to run
call back starts
Message from Main thread.
The input number is : 23
call back ends
記得以前的代碼,寫的都不是很好。雖然call.BeginInvoke可以開始非同步呼叫,但幾乎就沒有使用過EndInvoke。EndInvoke可以保證非同步呼叫被正常結束,使代碼更加健康。
非同步呼叫,可以使代碼具有更高的執行效率,但是在非同步呼叫時,應該有一個健康的使用習慣。