.NET Framework的IAsyncResult接口的细节
请尊重原作者的工作,转载时请务必注明转载自:www.xionggf.com
概述
IAsynResult接口用来表征一个异步操作的结果。它的定义声明如下:
1[System.Runtime.InteropServices.ComVisible(true)]
2public interface IAsyncResult
3{
4 object AsyncState { get; }
5 WaitHandle AsyncWaitHandle { get; }
6 bool CompletedSynchronously { get; }
7 bool IsCompleted { get; }
8}
有一些.NET Framework预定义的类是继承实现这个接口,如下:
- AsyncResult
- SecurityTokenProvider.SecurityTokenAsyncResult
- AsyncResult
- Task
- CommittableTransaction
示例程序
接下来的示例演示了如何使用了IAsyncResult接口中的AsyncWaitHandle属性,去获取到一个WaitHandle类型的值,以及如何使用一个delegate去等待一个异步调用。当异步调用完成后,WaitHandle类型的返回值将会被赋值上。这示例由两个类组成,一个是包含了异步调用函数的类;另一个类则是包含了调用异步函数的方法。
1using System;
2using System.Threading;
3
4namespace Examples.AdvancedProgramming.AsynchronousOperations
5{
6 public class AsyncDemo
7 {
8 // 将要被异步执行的函数
9 public string TestMethod(int callDuration, out int threadId)
10 {
11 Console.WriteLine("Test method begins.");
12 Thread.Sleep(callDuration); // 被异步执行的函数所在的线程休眠callDuration所指定的时间
13 threadId = Thread.CurrentThread.ManagedThreadId; // 拿到系统给本异步执行的函数分配的运行线程的id
14 return String.Format("My call time was {0}.", callDuration.ToString());
15 }
16 }
17
18 // 将要被异步执行的函数的签名声明
19 public delegate string AsyncMethodCaller(int callDuration, out int threadId);
20}
调用AsyncDemo的类如下:
1using System;
2using System.Threading;
3namespace Examples.AdvancedProgramming.AsynchronousOperations
4{
5 public class AsyncMain
6 {
7 static void Main()
8 {
9 int threadId;
10 AsyncDemo ad = new AsyncDemo();
11
12 // 创建一个delegate,这个delegate指向AsyncDemo.TestMethod方法
13 AsyncMethodCaller caller = new AsyncMethodCaller(ad.TestMethod);
14
15 // 这里的BeginInvoke是Delegate的异步调用方法,该方法有以下特性:
16 // a、委托的BeginInvoke方法,在线程池分配的子线程中执行委托
17 // b、委托执行时不会阻塞主线程(调用委托的BeginInvoke线程),主线程继续向下执行。
18 // c、委托执行时会阻塞子线程。
19 // d、委托结束时,如果有返回值,子线程讲返回值传递给主线程;如果有回调函数,子线程
20 // 将继续执行回调函数。
21 // 参考网页
22 // https://www.cnblogs.com/EasonLeung/p/3683492.html
23 // https://www.cnblogs.com/markhe/articles/5587956.html
24 // https://www.jb51.net/article/155167.htm
25
26 // 第一个参数就是AsyncMethodCaller函数签名中的int callDuration参数
27 // 第二个参数就是AsyncMethodCaller函数签名中的out int threadId参数
28 IAsyncResult result = caller.BeginInvoke(3000, out threadId, null, null);
29
30 Thread.Sleep(0);
31 Console.WriteLine("Main thread {0} does some work.",Thread.CurrentThread.ManagedThreadId);
32
33 // Wait for the WaitHandle to become signaled.
34 // 执行本句代码之后,会阻塞当前运行的线程,直到WaitHanle得到赋值为止
35 result.AsyncWaitHandle.WaitOne();
36
37 // 参考网址: https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.waithandle.waitone?view=netframework-3.5#System_Threading_WaitHandle_WaitOne
38 // WaitHanle得到赋值之后,本线程可以继续执行下去了,要获取到本次delegate调用的回调值,需要
39 // 调用EndInvoke方法
40 string returnValue = caller.EndInvoke(out threadId, result);
41
42 // 获取完毕之后,关闭wait handle
43 result.AsyncWaitHandle.Close();
44
45 Console.WriteLine("The call executed on thread {0}, with return value \"{1}\".",
46 threadId, returnValue);
47 }
48 }
49}
上面的代码执行流程大致是:
- 主线程1执行相关的初始化工作Main thread 1 does some work。
- 调用BeginInvoke方法,启动TestMethod该函数,此方法将会在另一个线程3中执行此函数。
- 调用BeginInvoke方法会马上返回一个IAsyncResult类型的返回值,调用该返回值的WaitHandle成员AsyncWaitHandle的WaitOne方法阻塞本线程1直到线程3结束返回为止。
- 线程1恢复后,接下来可以调用EndInvoke方法取到回调值。
- 调用IAsyncResult类型的返回值的AsyncWaitHandle成员的Close方法结束操作。
IAsyncResult的属性描述表
属性名 | 描述 |
---|---|
AsyncState | 获取一个用户定义的对象,该对象限定或包含有关异步操作的信息。 |
AsyncWaitHandle | 获取用于等待异步操作完成的 WaitHandle。 |
CompletedSynchronously | 获取一个值,该值指示异步操作是否同步完成。 |
IsCompleted | 获取一个值,该值指示异步操作是否已完成。 |
WaitHandle.WaitOne的一些细节
##参考网页: https://docs.microsoft.com/en-us/dotnet/api/system.iasyncresult?view=netframework-4.8