/// <summary> /// Handler1的等价代码 /// </summary> /// <param name="vv"></param> /// <returns></returns> public static Task Handler1No_awiter(int vv) { Handler1StateMachine h1s = new Handler1StateMachine(); h1s.vv = vv; h1s.state = -1; h1s.builder = System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Create(); h1s.builder.Start(ref h1s); return(h1s.builder.Task); }
/// <summary> /// 官方的等价翻译 /// 翻译等价代码的技巧: /// 按照原代码的顺序从上往下写,遇到await语句,就转成xxx.GetAwaiter(),并且定义一个对应的TaskAwaiter类型字段 /// 然后进入IsCompleted判断,每个await语句对应的判断块都类似,不同点:把state设为不同值,这里为方便阅读代码,按照代码顺序递增state的值 /// 关键方法:builder.AwaitUnsafeOnCompleted;这个方法不会阻塞,当前方法所在线程直接return,去执行其它任务,类库内部帮我们后续再回调到MoveNext /// 然后定义一个标签位置,后续代码写在标签之后 /// </summary> public void MoveNext() { //这里就是配合下面翻译的代码,做的配合工作 switch (this.state) { case 0: goto block0; case 1: goto block1; default: break; } //翻译等价代码的技巧: //按照原代码的顺序从上往下写,遇到await语句,就转成xxx.GetAwaiter(),并且定义一个对应的TaskAwaiter类型字段 //然后进入IsCompleted判断,每个await语句对应的判断块都类似,不同点:把state设为不同值,这里为方便阅读代码,按照代码顺序递增state的值 //然后定义一个标签位置,后续代码写在标签之后 Console.WriteLine("进入Handler1"); this.awaiterDelay2000 = Task.Delay(2000).GetAwaiter(); if (!this.awaiterDelay2000.IsCompleted) { this.state = 0; Handler1StateMachine h1s = this; this.builder.AwaitUnsafeOnCompleted(ref this.awaiterDelay2000, ref h1s); return; } block0: this.awaiterDelay2000.GetResult(); Console.WriteLine("执行完Task.Delay(2000)"); this.awaiterHandler2 = Program.Handler2(this.vv).GetAwaiter(); if (!this.awaiterHandler2.IsCompleted) { this.state = 1; Handler1StateMachine h1s = this; this.builder.AwaitUnsafeOnCompleted(ref this.awaiterHandler2, ref h1s); return; } block1: var rt = this.awaiterHandler2.GetResult(); this.value = rt; Console.WriteLine("执行完Handler2"); this.state = -2; this.builder.SetResult(); }
/// <summary> /// 简单粗暴翻译 /// 翻译等价代码的技巧: /// 按照原代码的顺序从上往下写,遇到await语句,就转成xxx.GetAwaiter(),并且定义一个对应的TaskAwaiter类型字段 /// 不做IsCompleted,全部利用builder.AwaitUnsafeOnCompleted方法结束当前方法,释放当前线程 /// 弊端:遇到Task.FromResult这种代码,就会有点浪费,因为没必要builder.AwaitUnsafeOnCompleted /// </summary> public void MoveNext2() { //翻译等价代码的技巧: //按照原代码的顺序从上往下写,遇到await语句,就转成xxx.GetAwaiter(),并且定义一个对应的TaskAwaiter类型字段 //不做IsCompleted,全部利用builder.AwaitUnsafeOnCompleted方法结束当前方法,释放当前线程 // Handler1StateMachine h1s = this; switch (this.state) { case 0: Console.WriteLine("进入Handler1"); this.awaiterDelay2000 = Task.Delay(2000).GetAwaiter(); this.state = 1; this.builder.AwaitUnsafeOnCompleted(ref this.awaiterDelay2000, ref h1s); return; case 1: this.awaiterDelay2000.GetResult(); Console.WriteLine("执行完Task.Delay(2000)"); this.awaiterHandler2 = Program.Handler2(this.vv).GetAwaiter(); this.state = 2; this.builder.AwaitUnsafeOnCompleted(ref this.awaiterHandler2, ref h1s); return; case 2: var rt = this.awaiterHandler2.GetResult(); this.value = rt; Console.WriteLine("执行完Handler2"); this.state = 3; this.builder.SetResult(); return; default: break; } }