这几天,看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的返回值
02 | using System.Collections.Generic; |
04 | using System.Windows.Forms; |
05 | using System.Threading; |
06 | using System.Runtime.Remoting.Messaging; |
12 | /// The main entry point for the application. |
17 | AsyncFuncDelegate caller = new AsyncFuncDelegate(Func); |
18 | Console.WriteLine( "Input number please..." ); |
19 | IAsyncResult result = caller.BeginInvoke(Convert.ToInt32(Console.ReadLine()), null , null ); |
20 | Console.WriteLine( "Implement other tasks" ); |
22 | Console.WriteLine( "Implement other tasks end ..." ); |
23 | Console.WriteLine( "Get user's input" ); |
24 | Console.WriteLine(caller.EndInvoke(result)); |
27 | delegate string AsyncFuncDelegate( int userInput); |
28 | static string Func( int userInput) |
30 | Console.WriteLine( "Func start to run" ); |
31 | Console.WriteLine( "..." ); |
33 | Console.WriteLine( "Func end to run" ); |
34 | 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的返回值
03 | AsyncFuncDelegate caller = new AsyncFuncDelegate(Func); |
04 | Console.WriteLine( "Input number please..." ); |
05 | IAsyncResult result = caller.BeginInvoke(Convert.ToInt32(Console.ReadLine()), null , null ); |
06 | Console.WriteLine( "Implement task 1" ); |
07 | result.AsyncWaitHandle.WaitOne(); |
08 | result.AsyncWaitHandle.Close(); |
09 | Console.WriteLine( "Implment task 2" ); |
10 | Console.WriteLine( "Get user's input" ); |
11 | Console.WriteLine(caller.EndInvoke(result)); |
输出结果如下:
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的返回值
04 | AsyncFuncDelegate caller = new AsyncFuncDelegate(Func); |
05 | Console.WriteLine( "Input number please..." ); |
06 | IAsyncResult result = caller.BeginInvoke(Convert.ToInt32(Console.ReadLine()), null , null ); |
07 | while (!result.IsCompleted) |
12 | Console.WriteLine( "" ); |
13 | Console.WriteLine( "Implement other task2" ); |
14 | Console.WriteLine( "Get user's input" ); |
15 | Console.WriteLine(caller.EndInvoke(result)); |
输出结果如下:
Func start to run
...
>>>>>Func end to run
>
Implement other task2
Get user's input
23
2 不需要在当前线程中获取返回值,但是仍然需要对返回值做处理
02 | using System.Collections.Generic; |
04 | using System.Windows.Forms; |
05 | using System.Threading; |
06 | using System.Runtime.Remoting.Messaging; |
12 | /// The main entry point for the application. |
17 | AsyncFuncDelegate caller = new AsyncFuncDelegate(Func); |
18 | Console.WriteLine( "Input number please..." ); |
19 | caller.BeginInvoke(Convert.ToInt32(Console.ReadLine()), new AsyncCallback(CallBackFunc), "Message from Main thread." ); |
20 | Console.WriteLine( "Main thread ends" ); |
23 | delegate string AsyncFuncDelegate( int userInput); |
24 | static string Func( int userInput) |
26 | Console.WriteLine( "Func start to run" ); |
27 | Console.WriteLine( "..." ); |
29 | Console.WriteLine( "Func end to run" ); |
30 | return userInput.ToString(); |
32 | static void CallBackFunc(IAsyncResult ar) |
34 | AsyncResult result = ar as AsyncResult; |
35 | string inputMessage = result.AsyncState as string ; |
36 | AsyncFuncDelegate caller = result.AsyncDelegate as AsyncFuncDelegate; |
37 | Console.WriteLine( "call back starts" ); |
38 | Console.WriteLine(inputMessage); |
39 | Console.WriteLine( "The input number is : " + caller.EndInvoke(ar)); |
40 | 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可以保证异步调用被正常结束,使代码更加健康。
异步调用,可以使代码具有更高的执行效率,但是在异步调用时,应该有一个健康的使用习惯。