网站实名认证怎么做,网站系统建设开票要开什么,安平做网站的电话,iknowledge wordpress在用async包裹的方法体中#xff0c;可以使用await关键字以同步的方式编写异步调用的代码。那么它的内部实现原理是什么样的呢#xff1f;我们是否可以自定义await以实现定制性的需求呢#xff1f;先来看一个简单的例子#xff1a; 1 class Test {2 public sta… 在用async包裹的方法体中可以使用await关键字以同步的方式编写异步调用的代码。那么它的内部实现原理是什么样的呢我们是否可以自定义await以实现定制性的需求呢先来看一个简单的例子 1 class Test {2 public static void Main (string[] args) {3 Task.Run (new FuncTaskstring(task1));4 Console.ReadLine ();5 }6 7 private async static Taskstring task1() {8 string ret await task2 ();9 Console.WriteLine (Await Task Result: ret);
10 return ret;
11 }
12
13 private static Taskstring task2() {
14 return Task.FromResultstring (Task2);
15 }
16 } 通过ILSpy反编译要关闭视图-选项-反编译await/async菜单项得到如下代码 1 internal class Test2 {3 [CompilerGenerated]4 [StructLayout(LayoutKind.Auto)]5 private struct task1d__0 : IAsyncStateMachine6 {7 public int 1__state;9 public AsyncTaskMethodBuilderstring t__builder;
11 public string ret5__1;
13 private TaskAwaiterstring u__$awaiter2;
15 private object t__stack;
16
17 void IAsyncStateMachine.MoveNext()
18 {
19 string result;
20 try
21 {
22 int num this.1__state;
23 if (num ! -3)
24 {
25 TaskAwaiterstring taskAwaiter;
26 if (num ! 0)
27 {
28 taskAwaiter Test.task2().GetAwaiter();
29 if (!taskAwaiter.IsCompleted)
30 {
31 this.1__state 0;
32 this.u__$awaiter2 taskAwaiter;
33 this.t__builder.AwaitUnsafeOnCompletedTaskAwaiterstring, Test.task1d__0(ref taskAwaiter, ref this);
34 return;
35 }
36 }
37 else
38 {
39 taskAwaiter this.u__$awaiter2;
40 this.u__$awaiter2 default(TaskAwaiterstring);
41 this.1__state -1;
42 }
43 string arg_86_0 taskAwaiter.GetResult();
44 taskAwaiter default(TaskAwaiterstring);
45 string text arg_86_0;
46 this.ret5__1 text;
47 Console.WriteLine(Await Task Result: this.ret5__1);
48 result this.ret5__1;
49 }
50 }
51 catch (Exception exception)
52 {
53 this.1__state -2;
54 this.t__builder.SetException(exception);
55 return;
56 }
57 this.1__state -2;
58 this.t__builder.SetResult(result);
59 }
60
61 [DebuggerHidden]
62 void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine param0)
63 {
64 this.t__builder.SetStateMachine(param0);
65 }
66 }
67
68 public static void Main(string[] args)
69 {
70 Task.Runstring(new FuncTaskstring(Test.task1));
71 Console.ReadLine();
72 }
73
74 [DebuggerStepThrough, AsyncStateMachine(typeof(Test.task1d__0))]
75 private static Taskstring task1()
76 {
77 Test.task1d__0 task1d__;
78 task1d__.t__builder AsyncTaskMethodBuilderstring.Create();
79 task1d__.1__state -1;
80 AsyncTaskMethodBuilderstring t__builder task1d__.t__builder;
81 t__builder.StartTest.task1d__0(ref task1d__);
82 return task1d__.t__builder.Task;
83 }
84
85 private static Taskstring task2()
86 {
87 return Task.FromResultstring(Task2);
88 }
89 } 按照代码的调用顺序我们关注下task1()的内部实现。 首先是初始化结构体task1d_0的实例task1d__。那么task1d__0是个什么东东呢由编译器的生成代码中可以看到它是一个实现了IAsyncStateMachine接口的结构体而用户代码则被编译器重新组织进了MoveNext()方法中。task1d__0有个内部状态成员1__stateMoveNext()方法根据这个状态调转到相应的代码块中加以执行。 了解了task1d__0的声明实现再看下task1()方法中的具体调用。在创建实例task1d__之后设置初始状态1__state为-1并调用t__builder的Start方法。不难推断在Start方法中会调用task1d__.MoveNext()此时内部状态为-1会先调用Test.task2().GetAwaiter()获取其所关联的TaskAwaiter实例。如果awaiter当前是未结束的话则设置1__state为0并将当前task1d__作为参数关联到TaskAwaiter实例的onCompletedContinuation回调延续中去。当未来某个时刻TaskAwaiter所关联的Task任务结束时会设置awaiter的异步结果并触发回调延续导致调用task1d__.MoveNext()方法并最终跳转到用户代码块中获取awaiter的异步结果并交由用户代码处理。这个回调基于Task.ConfigureAwait(true/false)的不同会在后续切换到当前线程或是从线程池中取了一个空闲线程来处理(更细节可参考.net源码分析)。 这里要顺便提一句在本例中通过Task.Run创建了taskX1await之后的代码与taskX1没有任何关系从编译器生成的代码来看在调用task1()方法并调用task1d__.Start()方法之后taskX便结束了虽然task1()方法返回了新的Taskstring实例但是只是特定类型的返回值而已与taskX1或Task没有任何关系。 由以上分析可以看到async/await只是一个语法糖async告知编译器要生成状态机代码await则是配合生成GetAwaiter()并封装跳转的用户代码块。除此之外async/await与Task没有任何直接关系。而TaskAwaiter的作用是实现INotifyCompletion(在System.Runtime.CompilerServices命名空间)以桥接异步回调过程。那么第二个自定义await的问题便一目了然了任何类型只需要实现GetAwaiter()方法以返回INotifyCompletion实例便可以被await。 举个例子 1 class TestAwaiterT : INotifyCompletion {2 private T result;3 private Action continuation;4 5 // INotifyCompletion Implement6 public void OnCompleted(Action continuation) { this.continuation continuation; }7 8 // Compiler Call Methods9 public bool IsCompleted { get; private set; }
10 public T GetResult() { return result; }
11 public TestAwaiterT GetAwaiter() { return this; } // Self Call Methods
12 public void SetResult(T ret) {
13 result ret;
14 if (continuation ! null) {
15 continuation ();
16 }
17 }
18 }
19
20 class Test {
21 public static void Main (string[] args) {
22 Task.Run (new Action(task1));
23 Console.ReadLine ();
24 }
25
26 private async static void task1() {
27 Console.WriteLine (Begin await:);
28 int ret await testAwaiter ();
29 Console.WriteLine (Await Task Result: ret);
30 }
31
32 private static TestAwaiterint testAwaiter() {
33 TestAwaiterint awaiter new TestAwaiterint ();
34 ThreadPool.QueueUserWorkItem (_ {
35 Thread.Sleep(3000);
36 awaiter.SetResult (100);
37 });
38 return awaiter;
39 }
40 } 这里没有再定义单独的类型以返回TestAwaiter而是把二者都封装在了TestAwaiter内部。运行结果如下 Begin await: Await Task Result:100转载于:https://www.cnblogs.com/Jackie-Snow/p/6542372.html