Last active
October 4, 2021 23:35
-
-
Save Kagre/8f77b12978e4c26bc89f4a7203d7a18f to your computer and use it in GitHub Desktop.
Un-Winding a C# Async/Await
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
////////////////////////////////////////////////////////////////////////////////////// | |
// https://bytelanguage.net/2020/05/31/tpl-and-asynchronous-programming/ | |
// https://www.markopapic.com/csharp-under-the-hood-async-await/ | |
using System; | |
using System.Threading.Tasks; | |
namespace MyApplication{public class Program{ | |
public static void Main(string[] args){ | |
Foo(10).Wait(); | |
} | |
static async Task Foo(int delay){ | |
Console.WriteLine("FooStart"); | |
await Task.Delay(delay); | |
Console.WriteLine(delay); | |
await Bar(); | |
Console.WriteLine("FooDone"); | |
} | |
static async Task Bar(){ | |
await Task.Delay(100); | |
} | |
}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
////////////////////////////////////////////////////////////////////////////////////// | |
// https://bytelanguage.net/2020/06/08/asynchronous-code-behind-the-scenes-004/ | |
using System; | |
using System.Threading.Tasks; | |
using System.Runtime.CompilerServices; | |
namespace MyApplication{public class Program{ | |
struct FooStateMachine : IAsyncStateMachine{ | |
public int delay; | |
public Task Task{ | |
get => t__builder.Task; | |
} | |
public void Start(){ | |
i__state = -1; | |
t__builder = AsyncTaskMethodBuilder.Create(); | |
t__builder.Start(ref this); | |
} | |
AsyncTaskMethodBuilder t__builder; | |
int i__state; | |
TaskAwaiter awaiter; | |
void IAsyncStateMachine.MoveNext(){ | |
try{ | |
switch(i__state){ | |
case -2: goto Completed; | |
case -1: goto Started; | |
case 0: goto ResumePoint1; // Task.Delay(delay); has completed | |
case 1: goto ResumePoint2; // Bar(); has completed | |
default: goto Completed; | |
} | |
Started: | |
Console.WriteLine("FooStart"); | |
awaiter = Task.Delay(delay).GetAwaiter(); | |
i__state = 0; | |
if(!awaiter.IsCompleted){ | |
t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this); | |
return; | |
} | |
ResumePoint1: | |
awaiter.GetResult(); | |
Console.WriteLine(delay); | |
awaiter = Bar().GetAwaiter(); | |
i__state = 1; | |
if(!awaiter.IsCompleted){ | |
t__builder.AwaitUnsafeOnCompleted(ref awaiter, ref this); | |
return; | |
} | |
ResumePoint2: | |
awaiter.GetResult(); | |
Console.WriteLine("FooDone"); | |
awaiter = default(TaskAwaiter); | |
Completed: | |
i__state = -2; | |
}catch (Exception exception){ | |
i__state = -2; | |
t__builder.SetException(exception); | |
return; | |
} | |
t__builder.SetResult(); | |
} | |
void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine){ | |
t__builder.SetStateMachine(stateMachine); | |
} | |
} | |
public static void Main(string[] args){ | |
Foo(10).Wait(); | |
} | |
static Task Foo(int delay){ | |
var FooMachine = new FooStateMachine(); | |
FooMachine.delay = delay; | |
FooMachine.Start(); | |
return FooMachine.Task; | |
} | |
static async Task Bar(){ | |
await Task.Delay(100); | |
} | |
}} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment