ã³ã³ãã€ã©ã«ããéåæã³ãŒãå€æã®è©³çŽ°
éåæã¡ã«ããºã ã¯ã.NETããŒã¹ã¯ã©ã¹ã©ã€ãã©ãªã®ãµããŒãã«ãããCïŒã³ã³ãã€ã©ã«å®è£
ãããŸãã ã©ã³ã¿ã€ã èªäœã¯å€æŽããå¿
èŠããããŸããã§ããã ã€ãŸããawaitããŒã¯ãŒãã¯ã以åã®ããŒãžã§ã³ã®CïŒã§èšè¿°ã§ãããã¥ãŒã«å€æããããšã§å®è£
ãããŸãã .NET ReflectorãŸãã¯ILSpyãã³ã³ãã€ã©ãŒã䜿çšããŠãçæãããã³ãŒãã調ã¹ãããšãã§ããŸãã ããã¯èå³æ·±ãã ãã§ãªãããããã°ãããã©ãŒãã³ã¹åæãããã³éåæã³ãŒãã®ä»ã®ã¿ã€ãã®èšºæã«ã圹ç«ã¡ãŸãã
ã¹ã¿ãæ³
ãŸããéåæã¡ãœããã®ç°¡åãªäŸãèããŠã¿ãŸãããã
public async Task<Int32> MethodTaskAsync() { Int32 one = 33; await Task.Delay(1000); return one; }
ãã®äŸã¯éåžžã«åçŽã§ãããéåæ/åŸ
æ©ã®å®è£
ã®åºæ¬åçã説æããã®ã«ååå®çšçã§äŸ¿å©ã§ãã ILSpyãå®è¡ããCïŒã³ã³ãã€ã©ãŒãèªåçã«çæããã³ãŒãã調ã¹ãŸãã
[AsyncStateMachine(typeof(Program.<MethodTaskAsync>d__0))] public Task<int> MethodTaskAsync() { Program.<MethodTaskAsync>d__0 <MethodTaskAsync>d__ = new Program.<MethodTaskAsync>d__0(); <MethodTaskAsync>d__.<>4__this = this; <MethodTaskAsync>d__.<>t__builder = AsyncTaskMethodBuilder<int>.Create(); <MethodTask>d__.<>1__state = -1; AsyncTaskMethodBuilder<int> <>t__builder = <MethodTaskAsync>d__.<>t__builder; <>t__builder.Start<Program.<MethodTaskAsync>d__0>(ref <MethodTaskAsync>d__); return <MethodTaskAsync>d__.<>t__builder.Task; }
é¢çœãã§ããã asyncããŒã¯ãŒãã¯ãã¡ãœãããå€éšã§äœ¿çšãããæ¹æ³ã«ã¯åœ±é¿ããŸããã ããã¯ãã³ã³ãã€ã©ã«ãã£ãŠçæãããã¡ãœããã®ã·ã°ããã£ããéåæãšããåèªãé€ããŠå
ã®ã¡ãœããã«å¯Ÿå¿ãããããé¡èã§ãã ããçšåºŠãŸã§ãéåææå®åã¯ã¡ãœããã·ã°ããã£ã®äžéšãšã¯èŠãªãããŸãããããšãã°ãä»®æ³ã¡ãœããã®ãªãŒããŒã©ã€ããã€ã³ã¿ãŒãã§ã€ã¹ã®å®è£
ããŸãã¯åŒã³åºãã®å Žåã§ãã
asyncããŒã¯ãŒãã®å¯äžã®ç®çã¯ã察å¿ããã¡ãœããã®ã³ã³ãã€ã«æ¹æ³ãå€æŽããããšã§ãããç°å¢ãšã®çžäºäœçšã«ã¯åœ±é¿ããŸããã ãŸãããæ°ãããã¡ãœããã«ã¯å
ã®ã³ãŒãã®çè·¡ããªãããšã«æ³šæããŠãã ããã
ã¹ããŒããã·ã³æ§é
äžèšã®äŸã§ã¯ãã³ã³ãã€ã©ãŒã¯AsyncStateMachineå±æ§ãã¡ãœããã«èªåçã«é©çšããŸããã ã¡ãœããïŒMethodTaskAsyncïŒã«éåæ修食åãããå Žåãã³ã³ãã€ã©ã¯ã¹ããŒããã·ã³æ§é ãå«ãILãçæããŸãã
ãã®æ§é ã«ã¯ãã¡ãœããå
ã®ã³ãŒããå«ãŸããŠããŸãã ILã³ãŒãã«ã¯ãã¹ããŒããã·ã³ã§åŒã³åºãããã¹ã¿ãã¡ãœããïŒMethodTaskAsyncïŒãå«ãŸããŠããŸãã ã³ã³ãã€ã©ã¯ã察å¿ããã¹ããŒããã·ã³ãèå¥ã§ããããã«ãAsyncStateMachineå±æ§ãã¹ã¿ãã¡ãœããã«è¿œå ããŸãã ããã¯ãããã°ã©ã ãåŸ
æ©ç¶æ
ã«ãªã£ãæç¹ã§ã¡ãœããã®ç¶æ
ãä¿åã§ãããªããžã§ã¯ããäœæããããã«å¿
èŠã§ãã çµå±ã®ãšããããåç¥ã®ããã«ããã®ããŒã¯ãŒãã®åã®ã³ãŒãã¯åŒã³åºãã¹ã¬ããã§å®è¡ãããå°éãããšãããã°ã©ã ã®å Žæã«é¢ããæ
å ±ãä¿åããããããããã°ã©ã ãåéãããšãã«å®è¡ãç¶ç¶ã§ããŸãã
ã³ã³ãã€ã©ã¯ç°ãªãåäœãããå¯èœæ§ããããŸãããã¹ãŠã®ã¡ãœããå€æ°ãä¿åããã ãã§ãã ãããããã®å Žåãå€ãã®ã³ãŒããçæããå¿
èŠããããŸãã ãã ãããã以å€ã®æ¹æ³ãã€ãŸããããã¿ã€ãã®ã€ã³ã¹ã¿ã³ã¹ãäœæãããã¹ãŠã®ã¡ãœããããŒã¿ããã®ãªããžã§ã¯ãã®ã¡ã³ããŒãšããŠä¿åããããšãã§ããŸãã 次ã«ããã®ãªããžã§ã¯ããä¿åãããšããã¹ãŠã®ããŒã«ã«ã¡ãœããå€æ°ãèªåçã«ä¿åãããŸãã ããã¯ãæéç¶æ
æ©æ¢°ãšåŒã°ãã圢æãããæ§é ãèšèšããããã®ã§ãã
ã€ãŸããç¶æ
ãã·ã³ã¯æœè±¡ãã·ã³ã§ããããã®å
éšç¶æ
ã®æ°ã¯æéã§ãã 倧ãŸãã«èšãã°ãç¶æ
ãã·ã³ã¯ããŠãŒã¶ãŒã®ç®ã«ã¯ãäœãã転éããŠããããäœããååŸã§ãããã©ãã¯ããã¯ã¹ã§ãã ããã¯éåžžã«äŸ¿å©ãªæœè±¡åã§ãããè€éãªã¢ã«ãŽãªãºã ãé ãããšãã§ããŸããããã«ãæéç¶æ
ãã·ã³ã¯éåžžã«å¹ççã§ãã ããã«ãåºåèªã圢æãããå
¥åæåã®æéã»ããããããŸãã ãŸããåå
¥åã·ã³ãã«ããã·ã³ãæ°ããç¶æ
ã«ç§»è¡ããããšã«ãçæããå¿
èŠããããŸãã ãã®å Žåãå
¥åç¶æ
ã¯éåææäœã®ç¶æ
ã«ãªãããã®å€ã«åºã¥ããŠãç¶æ
ãã·ã³ã¯ç¹å®ã®ç¶æ
ã圢æããããã«å¿ããŠã¿ã¹ã¯ïŒåºåã¯ãŒãïŒãžã®åå¿ã圢æããŸãã ãã®ã¢ãããŒãã«ãããéåæã¿ã¹ã¯ã®åœ¢æãšç®¡çãç°¡çŽ åãããŸãæéç¶æ
ãã·ã³ã«é¢ãã詳现æ
å ±ã¯ãã€ã³ã¿ãŒãããäžã«è©³çŽ°ãªèšäºãå€æ°æ²èŒãããŠããŸãã
ã¹ããŒããã·ã³ã¯ã¯ã©ã¹ã®åœ¢åŒã§åœ¢æããã次ã®ã¡ã³ããŒå€æ°ãå«ãŸããŸãã
public int32 '<>1__state'; private int32 '<one>5__1'; public Mechanism_async.Program '<>4__this'; public System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> '<>t__builder'; private System.Runtime.CompilerServices.TaskAwaiter '<>u__awaiter';
ãã¹ãŠã®å€æ°ã®ååã«ã¯ãã³ã³ãã€ã©ã«ãã£ãŠååãçæãããããšã瀺ãå±±æ¬åŒ§ãå«ãŸããŠããŸãã ããã¯ãçæãããã³ãŒãããŠãŒã¶ãŒã³ãŒããšç«¶åããªãããã«ããããã«å¿
èŠã§ããæ£ããCïŒã§ã¯ãå€æ°åã«å±±æ¬åŒ§ãå«ããããšãã§ããªãããã§ãã- æåã®å€æ°<> 1_stateã«ã¯ãå°éããawaitã¹ããŒãã¡ã³ãã®æ°ãæ ŒçŽãããŸãã åŸ
æ©ãçºçãããŸã§ããã®å€æ°ã®å€ã¯-1ã§ãã å
ã®ã¡ãœããã®ãã¹ãŠã®åŸ
æ©æŒç®åã«ã¯çªå·ãä»ããããäžæåæ¢ã®æç¹ã§åŸ
æ©çªå·ãç¶æ
å€æ°ã«å
¥åãããŸãããã®åŸãå®è¡ãåéããå¿
èŠããããŸãã
- 次ã®å€æ°<one> 5_1ã¯ãå
ã®å€æ°oneãæ ŒçŽããããã«äœ¿çšãããŸãã ã³ã³ãã€ã©ãŒã«ãã£ãŠçæãããã³ãŒãã§ã¯ããã®å€æ°ãžã®ãã¹ãŠã®åŒã³åºãã¯ããã®ã¡ã³ããŒå€æ°ãžã®åŒã³åºãã«çœ®ãæããããŸãã
- 次ã«ãå€æ°<> 4_thisãèŠã€ãããŸãã ããã¯ãééçéåæã¡ãœããã®ç¶æ
ãã·ã³ã§ã®ã¿æ€åºãããåŒã³åºããããªããžã§ã¯ãã«ä»£ãã£ãŠå«ãŸããŠããŸãã ããæå³ã§ã¯ãããã¯å¥ã®ããŒã«ã«ã¡ãœããå€æ°ã§ãããåããªããžã§ã¯ãã®ä»ã®å€æ°ã¡ã³ããŒã«ã¢ã¯ã»ã¹ããããã«ã®ã¿äœ¿çšãããŸãã éåæã¡ãœãããå€æããããã»ã¹ã§ã¯ãå
ã®ãªããžã§ã¯ãã®ã³ãŒããã¹ããŒããã·ã³ã®æ§é ã«è»¢éããããããéåæã¡ãœãããä¿åããŠæ瀺çã«äœ¿çšããå¿
èŠããããŸãã
- AsyncTaskMethodBuilderïŒ<> t__builderïŒ -ã¿ã¹ã¯ãè¿ãéåæã¡ãœããã®ãã«ããŒãè¡šããŸãã ãã®ãã«ããŒåãšãã®ã¡ã³ããŒã¯ãã³ã³ãã€ã©ãŒã«ãã£ãŠäœ¿çšãããããšãæå³ããŠããŸãã ããã«ããããã¹ãŠã®ã¹ããŒããã·ã³ã«å
±éã®ããžãã¯ãã«ãã»ã«åãããŸãã ã¹ã¿ãã«ãã£ãŠè¿ãããTaskãªããžã§ã¯ããäœæããã®ã¯ãã®ã¿ã€ãã§ãã å®éããã®ã¿ã€ãã¯ãåŸã§å®äºã§ããããããã¿ã¹ã¯ãäœæãããšããæå³ã§ãTaskCompletionSourceã¯ã©ã¹ã«éåžžã«äŒŒãŠããŸãã TaskCompletionSourceãšã®éãã¯ãAsyncTaskMethodBuilderãéåæã¡ãœããçšã«æé©åãããŠãããããã©ãŒãã³ã¹ãåäžãããããã«ãã¯ã©ã¹ã§ã¯ãªãæ§é äœã§ããããšã§ãã
- TaskAwaiterïŒ<> u_awaiterïŒ -ããã¯ãéåæã¿ã¹ã¯ã®å®äºãåŸ
ã€äžæãªããžã§ã¯ããä¿åãããå Žæã§ãã æ§é äœãšããŠãæ瀺ãããåŸ
æ©ãªãã¬ãŒã¿ãŒãã¿ã¹ã¯ãå®äºãããšããéç¥ã«ãµã€ã³ã¢ããããã®ã«åœ¹ç«ã¡ãŸãã
ã³ã³ãã€ã©ã®å
éšã§å®éã«äœãèµ·ãããã«ã€ããŠã®ãã詳现ãªç 究ã®ããã«ã<MethodTaskAsync> d__0ã®ã³ã³ãã€ã©ã«ãã£ãŠçæãããILã³ãŒããæ€èšããŠãã ããã
ILã³ãŒã .class nested private auto ansi sealed beforefieldinit '<MethodTaskAsync>d__0' extends [mscorlib]System.Object implements [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine { .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( 01 00 00 00 ) // Fields .field public int32 '<>1__state' .field public valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> '<>t__builder' .field public class Asynchronous.Program '<>4__this' .field private int32 '<one>5__1' .field private valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter '<>u__1' // Methods .method public hidebysig specialname rtspecialname instance void .ctor () cil managed { // Method begins at RVA 0x20ef // Code size 8 (0x8) .maxstack 8 IL_0000: ldarg.0 IL_0001: call instance void [mscorlib]System.Object::.ctor() IL_0006: nop IL_0007: ret } // end of method '<MethodTaskAsync>d__0'::.ctor .method private final hidebysig newslot virtual instance void MoveNext () cil managed { .override method instance void [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine::MoveNext() // Method begins at RVA 0x20f8 // Code size 185 (0xb9) .maxstack 3 .locals init ( [0] int32, [1] int32, [2] valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter, [3] class Asynchronous.Program/'<MethodTaskAsync>d__0', [4] class [mscorlib]System.Exception ) IL_0000: ldarg.0 IL_0001: ldfld int32 Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>1__state' IL_0006: stloc.0 .try { IL_0007: ldloc.0 IL_0008: brfalse.s IL_000c IL_000a: br.s IL_000e IL_000c: br.s IL_0054 IL_000e: nop IL_000f: ldarg.0 IL_0010: ldc.i4.s 33 IL_0012: stfld int32 Asynchronous.Program/'<MethodTaskAsync>d__0'::'<one>5__1' IL_0017: ldc.i4 1000 IL_001c: call class [mscorlib]System.Threading.Tasks.Task [mscorlib]System.Threading.Tasks.Task::Delay(int32) IL_0021: callvirt instance valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter [mscorlib]System.Threading.Tasks.Task::GetAwaiter() IL_0026: stloc.2 IL_0027: ldloca.s 2 IL_0029: call instance bool [mscorlib]System.Runtime.CompilerServices.TaskAwaiter::get_IsCompleted() IL_002e: brtrue.s IL_0070 IL_0030: ldarg.0 IL_0031: ldc.i4.0 IL_0032: dup IL_0033: stloc.0 IL_0034: stfld int32 Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>1__state' IL_0039: ldarg.0 IL_003a: ldloc.2 IL_003b: stfld valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>u__1' IL_0040: ldarg.0 IL_0041: stloc.3 IL_0042: ldarg.0 IL_0043: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>t__builder' IL_0048: ldloca.s 2 IL_004a: ldloca.s 3 IL_004c: call instance void valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32>::AwaitUnsafeOnCompleted<valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter, class Asynchronous.Program/'<MethodTaskAsync>d__0'>(!!0&, !!1&) IL_0051: nop IL_0052: leave.s IL_00b8 IL_0054: ldarg.0 IL_0055: ldfld valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>u__1' IL_005a: stloc.2 IL_005b: ldarg.0 IL_005c: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>u__1' IL_0061: initobj [mscorlib]System.Runtime.CompilerServices.TaskAwaiter IL_0067: ldarg.0 IL_0068: ldc.i4.m1 IL_0069: dup IL_006a: stloc.0 IL_006b: stfld int32 Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>1__state' IL_0070: ldloca.s 2 IL_0072: call instance void [mscorlib]System.Runtime.CompilerServices.TaskAwaiter::GetResult() IL_0077: nop IL_0078: ldloca.s 2 IL_007a: initobj [mscorlib]System.Runtime.CompilerServices.TaskAwaiter IL_0080: ldarg.0 IL_0081: ldfld int32 Asynchronous.Program/'<MethodTaskAsync>d__0'::'<one>5__1' IL_0086: stloc.1 IL_0087: leave.s IL_00a3 } // end .try catch [mscorlib]System.Exception { IL_0089: stloc.s 4 IL_008b: ldarg.0 IL_008c: ldc.i4.s -2 IL_008e: stfld int32 Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>1__state' IL_0093: ldarg.0 IL_0094: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>t__builder' IL_0099: ldloc.s 4 IL_009b: call instance void valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32>::SetException(class [mscorlib]System.Exception) IL_00a0: nop IL_00a1: leave.s IL_00b8 } // end handler IL_00a3: ldarg.0 IL_00a4: ldc.i4.s -2 IL_00a6: stfld int32 Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>1__state' IL_00ab: ldarg.0 IL_00ac: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>t__builder' IL_00b1: ldloc.1 IL_00b2: call instance void valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32>::SetResult(!0) IL_00b7: nop IL_00b8: ret } // end of method '<MethodTaskAsync>d__0'::MoveNext .method private final hidebysig newslot virtual instance void SetStateMachine ( class [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine stateMachine ) cil managed { .custom instance void [mscorlib]System.Diagnostics.DebuggerHiddenAttribute::.ctor() = ( 01 00 00 00 ) .override method instance void [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine::SetStateMachine(class [mscorlib]System.Runtime.CompilerServices.IAsyncStateMachine) // Method begins at RVA 0x21d0 // Code size 1 (0x1) .maxstack 8 IL_0000: ret } // end of method '<MethodTaskAsync>d__0'::SetStateMachine } // end of class <MethodTaskAsync>d__0
MoveNextã¡ãœãã
MethodTaskã¿ã€ãçšã«çæãããã¯ã©ã¹ã¯ãIAsyncStateMachineã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããŸããããã¯ãéåæã¡ãœããçšã«äœæãããã¹ããŒããã·ã³ãè¡šããŸãã ãã®ã¿ã€ãã¯ãã³ã³ãã€ã©ãŒå°çšã§ãã ãã®ã€ã³ã¿ãŒãã§ã€ã¹ã«ã¯ãMoveNextããã³SetStateMachineã®ã¡ã³ããŒãå«ãŸããŸãã MoveNextã¡ãœããã¯ãç¶æ
ãã·ã³ã次ã®ç¶æ
ã«ç§»åããŸãã ãã®ã¡ãœããã«ã¯å
ã®ã³ãŒããå«ãŸããŠãããã¡ãœããã®æåã®å
¥ãå£ãšåŸ
æ©ã®äž¡æ¹ã§åŒã³åºãããŸãã ã¹ããŒããã·ã³ã¯ãäœããã®åæç¶æ
ã§äœæ¥ãéå§ãããšèããããŠããŸãã æãåçŽãªéåæã¡ãœããã䜿çšããŠããMoveNextã³ãŒãã¯é©ãã»ã©è€éã§ãããããCïŒã®åçã®ã³ãŒãã§å¯èœãªéãæ£ç¢ºã«èª¬æããããã«ããŸãã
MoveNextã¡ãœããã®ååã¯ã以åã®ããŒãžã§ã³ã®CïŒã®å埩åãããã¯ã«ãã£ãŠçæãããMoveNextã¡ãœãããšé¡äŒŒããŠããããã§ãã ãããã®ãããã¯ã䜿çšãããšãyield returnããŒã¯ãŒãã䜿çšããŠãåäžã®ã¡ãœããã§IEnumerableã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ã§ããŸãã ãã®ç®çã§äœ¿çšãããæéç¶æ
ãã·ã³ã¯ãå€ãã®ç¹ã§éåæç¶æ
ãã·ã³ã«äŒŒãŠããŸãããããç°¡åã§ããäžéã³ãŒããæ€èšãããã®äžã§äœãèµ·ãããã確èªããŸãïŒä»¥äžã§ã¯ãã³ã³ãã€ã©ãŒãçæãããã®ã®ããå®å
šãªè°è«ã®ããã«CILèšèªãå®å
šã«èª¬æããããšã«ããæè¡çãªè©³çŽ°ãã¹ãããã§ããããã«ãã¹ãŠã®åœä»€ã説æããŸããïŒ
.locals init ( [0] int32, [1] int32, [2] valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter, [3] class Asynchronous.Program/'<MethodTaskAsync>d__0', [4] class [mscorlib]System.Exception )
- localsinitã¯ãã¡ãœããã«èšå®ããããã©ã°ã§ãããå€åã®ããŒã«ã«ã€ã³ã¹ã¿ã³ã¹ãåæåãã圹å²ãæãããŸãã ããã¯ã¡ãœããããããŒã§å®çŸ©ãããå€æ°ãCILã§åæåããå¿
èŠãããããšãæå³ããŸãã ããã§ã¯ããã®ã¡ãœããã§äœ¿çšããããã¹ãŠã®ã€ã³ã¹ã¿ã³ã¹ãå®çŸ©ããããããã¯æ
£äŸãšããŠé
åãšããŠå®çŸ©ãããããã©ã«ãã§èšå®ãããŸãïŒãªããžã§ã¯ãã¿ã€ãããã³ãªããžã§ã¯ããå«ãå€ã¿ã€ããã£ãŒã«ãã®å Žåã¯NULLãæŽæ°ã¿ã€ãã®å Žåã¯0ãæµ®åå°æ°ç¹ã
ãããã£ãŠãã¡ãœããã«å
¥ããšãã¡ãœããã§äœ¿çšããããã®æ¢è£œã®ããŒã«ã«å€æ°ãæ¢ã«ãããŸãã - valuetype-éèŠãªåãã€ãŸã æ§é
IL_0000: ldarg.0 IL_0001: ldfld int32 Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>1__state' IL_0006: stloc.0
- ldarg.0-åŒæ°0 ãã¹ã¿ãã¯ã«ããŒãããŸãã ã€ã³ããã¯ã¹0ã®åŒæ°ã¯ãçä¿¡åŒæ°ããã³ããŒãããèšç®ã¹ã¿ãã¯ïŒ.NETäžéèšèªã¯ã¹ã¿ãã¯èšèªã§ãïŒã«ããŒããããŸãã ããããã¡ãœããã«ã¯åŒæ°ããããŸããïŒ äºå®ãééçã¡ãœããã®ããã©ã«ãã§ã¯ãã€ã³ããã¯ã¹0ã®åŒæ°ã¯åžžã«ã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãžã®ãã€ã³ã¿ãŒã§ã-ããã åæã«åŒæ°ãããå Žåã¯ããã§ã«1ã2ãªã©ã®ã€ã³ããã¯ã¹ããããŸãã éçã¡ãœããã§ã¯ãåŒæ°ã¯0ããã«ãŠã³ããéå§ããŸãã
- ldfld-ãªããžã§ã¯ãã®ãã£ãŒã«ãå€ãæ€çŽ¢ããŸãããªã³ã¯ã¯ã¹ã¿ãã¯äžã«ãããŸãã ãããŠããªã³ã¯èªäœã¯ldarg.0ã䜿çšããŠäžèšã§ããŒããããŸãããããã®ãã£ãŒã«ãã«æ ŒçŽãããå€ã¯ããã«å¿ããŠã¹ã¿ãã¯ã«ããŒããããŸããã
- stloc.0-ã¹ã¿ãã¯ã®äžçªäžã®å€ïŒMethodTaskAsync.stateãªããžã§ã¯ããã£ãŒã«ãã®å€ïŒãååŸããã€ã³ããã¯ã¹0ã®ããŒã«ã«å€æ°ã®ãªã¹ãã«ä¿åããŸããããŒã«ã«å€æ°ã®ãªã¹ããlocalsinitã§å®£èšãããŸããã 䟿å©ã§ããã
IL_0007: ldloc.0 IL_0008: brfalse.s IL_000c IL_000a: br.s IL_000e IL_000c: br.s IL_0054 IL_000e: nop IL_000f: ldarg.0 IL_0010: ldc.i4.s 33 IL_0012: stfld int32 Asynchronous.Program/'<MethodTaskAsync>d__0'::'<one>5__1' IL_0017: ldc.i4 1000 IL_001c: call class [mscorlib]System.Threading.Tasks.Task [mscorlib]System.Threading.Tasks.Task::Delay(int32) IL_0021: callvirt instance valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter [mscorlib]System.Threading.Tasks.Task::GetAwaiter() IL_0026: stloc.2 IL_0027: ldloca.s 2 IL_0029: call instance bool [mscorlib]System.Runtime.CompilerServices.TaskAwaiter::get_IsCompleted() IL_002e: brtrue.s IL_0070
- ldloc.0ããã³brfalse.s-ã€ã³ããã¯ã¹0ã®ããŒã«ã«å€æ°ãèšç®ã¹ã¿ãã¯ã«ããŒãããŸãã ããã§ã¯ãä¿åãããã°ããã®ç¶æ
ãã¹ã¿ãã¯ã«ããŒããããç¶æ
å€ãfalseã®å Žåãã€ãŸãbrfalse.sã³ãã³ããå¶åŸ¡ãæçµåœä»€ã«ç§»ããŸãã 0.ã¡ãœãããåããŠå
¥åãããšãã®å€ã¯-1ã§ãããã¯åœä»€ã¹ããªãŒã ã®å®è¡ãããã«é²ãããšãæå³ããŸãã
- br.s IL_000e-æçµåœä»€ã®ç¡æ¡ä»¶è»¢éã ããã§ãå®è¡ããå¿
èŠãããã³ãŒãã®å¥ã®éšåã«ç§»åããŸãã ãã®å Žåã次ã®ã³ãã³ãã¯è¡IL_000eã§å®è¡ãããŸãã
- br.s IL_0054-ç¡æ¡ä»¶ãžã£ã³ãã§ããããbrfalse.sã³ãã³ããå®è¡ããããšããã®ã³ãã³ãã®ã¿ãå®è¡ãããŸã
- nop-æäœã³ãŒãã«ä¿®æ£ãå«ãŸããŠããå Žåãã¹ããŒã¹ãåããŸãã åŠçãµã€ã¯ã«ã¯å®äºã§ããŸãããéèŠãªæäœã¯å®è¡ãããŸããã
- ldarg.0ããã³ldc.i4.s 33-ããã§ã¯thisãã€ã³ã¿ãŒãããŒããããæ°å€33ãã¹ã¿ãã¯ã«ããŒããããŸããããã§ldc.i4.s-Int8åã®å€ãInt32ïŒçã圢åŒã®æžã蟌ã¿ïŒãšããŠèšç®ã¹ã¿ãã¯ã«ããã·ã¥ããŸãã
- stfld-ãªããžã§ã¯ããžã®åç
§ã«ããããªããžã§ã¯ãã®ãã£ãŒã«ãã®å€ãæ°ããå€ã«çœ®ãæããŸãã ããŒãããããã€ã³ã¿ãšã¹ã¿ãã¯äžã®æ°å€33ã䜿çšããŠãæ°ããå€33ãããŒããããã¡ã³ããŒå€æ°<one> 5_1ïŒããã©ã«ãã§0ã«åæåãããŸãïŒã«æ ŒçŽãããŸããã芧ã®ãšãããããã¯å
ã®ã¡ãœããã®æåã®è¡ã§ãã å
ã®ã¡ãœããã®ã³ãŒããå®è¡ãããã®ã¯ããã®ãããã¯ã§ãã
- ldc.i4 1000 -Int32åã®å€æ°ãInt32ãšããŠã¹ã¿ãã¯ã«ããŒãããŸãã
- åŒã³åºãã¯ã©ã¹[mscorlib] System.Threading.Tasks.Task [mscorlib] System.Threading.Tasks.Task :: DelayïŒint32ïŒ -ã¡ãœããã¯ããã§åŒã³åºãããŸãã ïŒcallvirtåœä»€ãšæ¯èŒããïŒãã®åœä»€ã®ç¹æ§ã¯ãåŒã³åºãããã¡ãœããã®ã¢ãã¬ã¹ãéçã«èšç®ãããããšã§ããã€ãŸããJITã³ã³ãã€ã«äžã§ãã£ãŠãã§ãã ãã®å ŽåãDelayã¡ãœããã¯éçã§ãã ãã®å ŽåãåŒã³åºãããã¡ãœããã®ãã©ã¡ãŒã¿ãŒã¯å·Šããå³ã«ã¹ã¿ãã¯ã«é
眮ããå¿
èŠããããŸããã€ãŸããæåã«æåã®ãã©ã¡ãŒã¿ãŒãã¹ã¿ãã¯ã«ããŒããã次ã«2çªç®ã«ãã©ã¡ãŒã¿ãŒãããŒãããå¿
èŠããããŸãã
- callvirt instance valuetype [mscorlib] System.Runtime.CompilerServices.TaskAwaiter [mscorlib] System.Threading.Tasks.Task :: GetAwaiterïŒïŒ -ãã®åœä»€ã¯ãåŒã³åºãããã¡ãœããã®ã¢ãã¬ã¹ãã¿ã€ãåæã«ãã£ãŠããã°ã©ã å®è¡äžã«æ±ºå®ããããšããç¹ã§äž»ã«åŒã³åºããšç°ãªããŸãã¡ãœãããåŒã³åºãããŠãããªããžã§ã¯ãã ããã«ãããããªã¢ãŒãã£ãºã ããµããŒãããããã«å¿
èŠãªé
延ãã€ã³ãã£ã³ã°ã®æŠå¿µãå®è£
ãããŸãã ãã®å Žåãæ»ãå€ïŒãã®å Žåã¯TaskAwaiterïŒã¯ã¹ã¿ãã¯ã«ããã·ã¥ãããŸããTaskAwaiterã¯ãéåæã¿ã¹ã¯ã®å®äºãåŸ
æ©ããŠãããªããžã§ã¯ããè¡šããŸãã
- stloc.2-ã¹ã¿ãã¯ã®äžçªäžã®å€ãååŸããã€ã³ããã¯ã¹2ã®ããŒã«ã«å€æ°ã®ãªã¹ãã«ä¿åããŸããã¹ã¿ãã¯ã®äžçªäžã®å€ã¯GetAwaiterïŒïŒãªãã¬ãŒã·ã§ã³ã®çµæã§ããããããã£ãŠãã®å€ã¯ã€ã³ããã¯ã¹2ã®ããŒã«ã«å€æ°ã«æ ŒçŽãããŸã
- ldloca.s 2-ã€ã³ããã¯ã¹2ã®ããŒã«ã«å€ãã¹ã¿ãã¯ã«èªã¿èŸŒã¿ãŸã-æè¿ä¿åããå€
- åŒã³åºãã€ã³ã¹ã¿ã³ã¹bool [mscorlib] System.Runtime.CompilerServices.TaskAwaiter :: get_IsCompletedïŒïŒ -ããããã£ã«ã¢ã¯ã»ã¹ãããšãã«ã¿ã¹ã¯ãå®äºãããã©ããã瀺ãå€ãã¹ã¿ãã¯ã«ããŒãããŸãïŒtrueãŸãã¯false
- brtrue.s IL_0070-ã¿ã¹ã¯ãå®äºããå Žåãå¥ã®ã³ãŒãã®å®è¡ã«é²ã¿ãŸããå®äºããŠããªãå Žåãå
ã«é²ã¿ãŸãã
ãããã£ãŠã次ã®ãããªã³ãŒããæ³åã§ããŸãã
public void MoveNext() { switch(this.1_state) { case -1: this.one = 33; var task = Task.Delay(1000); var awaiter = task.GetAwaiter();
äžèšã®ã³ãŒãã¯ãã¹ããŒããã·ã³ã®åæç¶æ
ãæ
åœããéåæã¿ã¹ã¯ã®å®äºã確èªããã¡ãœããã®é©åãªå Žæã«ç§»åããŸãã ãã®å ŽåããªãŒãããã³ã®ããã€ãã®ç¶æ
ã®1ã€ãžã®ç§»è¡ãçºçããŸããã¡ãœããã¯åŸ
ã¡åããå ŽæãŸãã¯åæçµäºã§äžæãããŸãã
äžæåæ¢æ¹æ³
ã¡ãœãããäžæãããå Žæã®ILã³ãŒããæ€èšããŸãã
IL_0030: ldarg.0 IL_0031: ldc.i4.0 IL_0032: dup IL_0033: stloc.0 IL_0034: stfld int32 Asynchronous.Program/'<MethosTaskAsync>d__0'::'<>1__state' IL_0039: ldarg.0 IL_003a: ldloc.2 IL_003b: stfld valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter Asynchronous.Program/'<MethosTaskAsync>d__0'::'<>u__1' IL_0040: ldarg.0 IL_0041: stloc.3 IL_0042: ldarg.0 IL_0043: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> Asynchronous.Program/'<MethosTaskAsync>d__0'::'<>t__builder' IL_0048: ldloca.s 2 IL_004a: ldloca.s 3 IL_004c: call instance void valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32>::AwaitUnsafeOnCompleted<valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter, class Asynchronous.Program/'<MethosTaskAsync>d__0'>(!!0&, !!1&) IL_0051: nop IL_0052: leave.s IL_00b8
ãã¹ãŠãäžèšã§èª¬æãããŠããããã«ãåæäœã説æãã䟡å€ã¯ãããŸããã
- ãã®ã³ãŒãã¯ãç¶æ
å€æ°ã0ã«å€æŽãã圹å²ãæãããŸããã³ãã³ãstfld int32 Asynchronous.Program / 'd__0' :: '<> 1__state'
I repeatã¯ããã£ãŒã«ãå€ãæ°ããå€ã«å€æŽããããšãæå³ããŸãã ãããŠãæ£ããå Žæããåéããã«ã¯ãç¶æ
å€æ°ãå€æŽããå¿
èŠããããŸãã
- 次ã«ã TaskAwaiterãªããžã§ã¯ãã䜿çšããŠã ã¿ã¹ã¯ã¿ã¹ã¯ã®å®äºã«é¢ããéç¥ããµãã¹ã¯ã©ã€ãããŸãã ããã¯ãã€ã³ããã¯ã¹2ã®ããŒã«ã«å€æ°ãã¹ã¿ãã¯ã«ããŒãããããã£ãŒã«ãå€ããã®ããŒã«ã«å€æ°ïŒ ldloc.2ããã³stfld valuetype [mscorlib] System.Runtime.CompilerServices.TaskAwaiter Asynchronous.Program / 'd__0' :: :: <>ã³ãã³ãã®å€ã«å€æŽããããšçºçããŸãu__1' ). , .
- AwaitUnsafeOnCompleted . await, , . awaiter. : AsyncTaskMethodBuilder.AwaitOnCompleted(ref TAwaiter awaiter, ref TStateMachine stateMachine) . 2 3, 2 â valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter, 3 â class Asynchronous.Program/'d__0'
AsyncTaskMethodBuilderæ§é ã詳ããèŠãŠã¿ãŸãããïŒãã®æ§é ãšããã«é¢é£ãããã¹ãŠã®ç 究ã«ã€ããŠã¯ããã€ãã®èšäºã§èª¬æã§ããã®ã§ãããã§ã¯è©³ãã説æããŸããïŒã /// <summary> default(TResult).</summary> internal readonly static Task<TResult> s_defaultResultTask = AsyncTaskCache.CreateCacheableTask(default(TResult)); /// <summary>, IAsyncStateMachine.</summary> private AsyncMethodBuilderCore m_coreState; // mutable struct: must not be readonly /// <summary> </summary> private Task<TResult> m_task; // lazily-initialized: must not be readonly /// <summary> /// , awaiter /// </summary> /// <typeparam name="TAwaiter"> awaiter.</typeparam> /// <typeparam name="TStateMachine"> .</typeparam> /// <param name="awaiter">The awaiter.</param> /// <param name="stateMachine"> .</param> [SecuritySafeCritical] public void AwaitUnsafeOnCompleted<TAwaiter, TStateMachine>( ref TAwaiter awaiter, ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion where TStateMachine : IAsyncStateMachine { try { AsyncMethodBuilderCore.MoveNextRunner runnerToInitialize = null; var continuation = m_coreState.GetCompletionAction(AsyncCausalityTracer.LoggingOn ? this.Task : null, ref runnerToInitialize); // await, if (m_coreState.m_stateMachine == null) { // var builtTask = this.Task; // internal-, // . m_coreState.PostBoxInitialization(stateMachine, runnerToInitialize, builtTask); } awaiter.UnsafeOnCompleted(continuation); } catch (Exception e) { AsyncMethodBuilderCore.ThrowAsync(e, targetContext: null); } }
ãã®æ§é ã®å
éšã«ãããã®ãç°¡åã«æ€èšããŠãã ããã- s_defaultResultTask = AsyncTaskCache.CreateCacheableTaskïŒããã©ã«ãïŒTResultïŒïŒ -ããã¯ãç¹å¥ãªDoNotDisposeãã©ã°ãæå®ãããšãã«Disposeãå®è£
ããã«ã¿ã¹ã¯ãäœæããŸãããã®ã¢ãããŒãã¯ããã£ââãã·ã¥ãŸãã¯åå©çšã®ããã®ã¿ã¹ã¯ãäœæãããšãã«äœ¿çšãããŸãã
- AsyncMethodBuilderCore m_coreState - IAsyncStateMachineã®å®è¡ã«é¢é£ä»ããããç¶æ
ãè¡šããŸãããããæ§é ã§ãã
- AsyncMethodBuilderCore.MoveNextRunner runnerToInitialize â MoveNext . , , MoveNext.
- m_coreState.GetCompletionAction(AsyncCausalityTracer.LoggingOn? this.Task: null, ref runnerToInitialize) â Action UnsafeOnCompleted . .
- awaiter.UnsafeOnCompletedïŒç¶ç¶ïŒ -ã€ã³ã¹ã¿ã³ã¹ã®å®è¡ãå®äºãããšãã«åŒã³åºãããã¢ã¯ã·ã§ã³ã®ç¶ç¶ãã¹ã±ãžã¥ãŒã«ããŸãããã®å Žåãã³ã³ããã¹ãã埩å
ããå¿
èŠããããã©ããã«å¿ããŠãMoveNextã¡ãœãããã³ã³ããã¹ããšã¡ãœããã®äžæåæ¢ã§åŒã³åºãããããã¿ã¹ã¯ãå®è¡ãããã¹ã¬ããã®ã³ã³ããã¹ãã§å®è¡ãç¶è¡ãããŸãã
ãããã«ç°ãªããœãŒã¹ã³ãŒããååŸããŸãã public void MoveNext() { switch(this.1_state) { case -1: this.one = 33; var task = Task.Delay(1000); var awaiter = task.GetAwaiter();
ã¡ãœããã®åé
ãã®ã³ãŒããå®è¡ããåŸãåŒã³åºãå
ã®ã¹ã¬ããã¯èªåã®ä»äºã«åãæãããŸãããçŸæç¹ã§ã¯ãã¿ã¹ã¯ãå®äºããã®ãåŸ
ã£ãŠããŸããã¿ã¹ã¯ãå®äºãããšãã¡ãœãããåã³åŒã³åºããMoveNextã¡ãœããïŒã¡ãœããåŒã³åºãã§AwaitUnsafeOnCompletedä»äºã®ããã«å¿
èŠãªãã¹ãŠãå®äºïŒãç¶è¡ãããšãã«åŒã³åºãããILã³ãŒããèããŸãã IL_0054: ldarg.0 IL_0055: ldfld valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>u__1' IL_005a: stloc.2 IL_005b: ldarg.0 IL_005c: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.TaskAwaiter Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>u__1' IL_0061: initobj [mscorlib]System.Runtime.CompilerServices.TaskAwaiter IL_0067: ldarg.0 IL_0068: ldc.i4.m1 IL_0069: dup IL_006a: stloc.0 IL_006b: stfld int32 Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>1__state' IL_0070: ldloca.s 2 IL_0072: call instance void [mscorlib]System.Runtime.CompilerServices.TaskAwaiter::GetResult() IL_0077: nop IL_0078: ldloca.s 2 IL_007a: initobj [mscorlib]System.Runtime.CompilerServices.TaskAwaiter IL_0080: ldarg.0 IL_0081: ldfld int32 Asynchronous.Program/'<MethodTaskAsync>d__0'::'<one>5__1' IL_0086: stloc.1 IL_0087: leave.s IL_00a3 IL_00a3: ldarg.0 IL_00a4: ldc.i4.s -2 IL_00a6: stfld int32 Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>1__state' IL_00ab: ldarg.0 IL_00ac: ldflda valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32> Asynchronous.Program/'<MethodTaskAsync>d__0'::'<>t__builder' IL_00b1: ldloc.1 IL_00b2: call instance void valuetype [mscorlib]System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1<int32>::SetResult(!0) IL_00b7: nop
- æåã®éšåã§ã¯ãã€ã³ããã¯ã¹0ã®åŒæ°ãèªã¿èŸŒãŸããŸã-ããã¯ãTaskAwaiter <> u__1 å€æ°ãæ€çŽ¢ããããã®å€ãã€ã³ããã¯ã¹2ã®ããŒã«ã«å€æ°ã«æ ŒçŽãããååæåãããŸãããã®åŸãå€-1ãã¹ã¿ãã¯ã«ããŒãããããã®å€ã1__stateå€æ°ã«ä¿åããããããã¿ã¹ã¯ã®ç¶æ
ããªã»ãããããŸãã
- 2çªç®ã®éšåã§ã¯ãããŒã«ã«å€æ°awaiterãã¹ã¿ãã¯ã«ããŒããããGetResultïŒïŒåŒã³åºããè¡ãããŸãã次ã«ãããŒã«ã«å€æ°ã®ã¹ã¿ãã¯ãžã®æ°ããããŒããšãã®æ°ããåæåã次ã«ãå€æ°5__1ãã¹ã¿ãã¯ã«ããŒããããã€ã³ããã¯ã¹1ã§ããŒã«ã«å€æ°ã«ä¿åãããå¥ã®ã³ãã³ããžã®ç§»è¡ãè¡ãããŸãã
- 3çªç®ã®éšåã§ã¯ã-2ãã¹ã¿ãã¯ã«ããŒããã1_stateå€æ°ã«æ ŒçŽããŸãã次ã«ãt_builderå€æ°ãã¹ã¿ãã¯ã«ããŒãããSetResultïŒ1ïŒã¡ãœãããåŒã³åºããŸãã
çµæã¯ãããããã®ãœãŒã¹ã³ãŒãã§ãã public void MoveNext() { switch(this.1_state) { case -1: this.one = 33; var task = Task.Delay(1000); var awaiter = task.GetAwaiter(); // , , ( IL-) if(!awaiter.IsCompleted) { this.1_state = 0; this.u__awaiter = awaiter; //u__awaiter TaskAwaiter t_builder.AwaitUnsafeOnCompleted(ref this.u_awaiter, ref <MethodTaskAsync>d__0); return; } case 0: var awaiter = this.u_awaiter; this.u_awaiter = new System.Runtime.CompilerServices.TaskAwaiter(); this.1_state = -1; awaiter.GetResult(); awaiter = new System.Runtime.CompilerServices.TaskAwaiter(); var one = this.<one>5_1; this.1_state = -2; this.t_builder.SetResult(one); } }
åæå®äº
åæçµäºã®å Žåãã¡ãœãããåæ¢ããŠåéããªãã§ãã ããããã®å Žåãã¡ãœããã®å®è¡ã確èªããgoto caseã¹ããŒãã¡ã³ãã䜿çšããŠé©åãªå Žæã«ç§»åããã ãã§ãã public void MoveNext() { switch(this.1_state) { case -1: this.one = 33; var task = Task.Delay(1000); var awaiter = task.GetAwaiter();
, , goto ....
ãã®èšäºã§ã¯ãAlex Davisã«ããCïŒ5.0ã®éåæããã°ã©ãã³ã°ã«é¢ãããæ°ã«å
¥ãã®æ¬ã®1ã€ã«äŸåããŸãããäžè¬ã«ãããã¯å°ããïŒå¿
èŠã«å¿ããŠ1æ¥ã§èªãããšãã§ããŸãïŒãéåžžã«èå³æ·±ããé©åºŠã«è©³çŽ°ã§éåæ/åŸ
æ©ã¡ã«ããºã å
šäœã説æããŠãããããå
šå¡ã«èªãããšããå§ãããŸããåæã«ãåå¿è
ã«ãèªãããšãã§ãããã¹ãŠãããã«éåžžã«ç°¡åã«æžãããŠããŸãïŒäººçã®äŸãªã©ïŒããããèªãã§äžŠè¡ããŠILã³ãŒããå匷ããŠãããšãæ¬ã«æžãããŠãããã®ãšå®éã«ããã«ãããã®ãšã®éã«ããããªççŸãèŠã€ãããŸãããããããã»ãšãã©ã®å Žåãã³ã³ãã€ã©ãå°ãä¿®æ£ããŠãããããã«ç°ãªãçµæãçæãå§ããå¯èœæ§ãæãé«ããšæããŸããããããããã¯ããã«ãã ããã»ã©éèŠã§ã¯ãããŸãããåæã«ããœãŒã¹ã³ãŒããšããŠïŒAsyncTaskMethodBuilderã説æããããã«ããã®ãªãœãŒã¹ã䜿çšããŸããïŒããã¯ãããã«æ·±ãæãäžããããšæã人ãããå Žåã§ãïŒã