Skip to content

Instantly share code, notes, and snippets.

@Kagre
Last active October 4, 2021 23:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Kagre/8f77b12978e4c26bc89f4a7203d7a18f to your computer and use it in GitHub Desktop.
Save Kagre/8f77b12978e4c26bc89f4a7203d7a18f to your computer and use it in GitHub Desktop.
Un-Winding a C# Async/Await
//////////////////////////////////////////////////////////////////////////////////////
// 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);
}
}}
//////////////////////////////////////////////////////////////////////////////////////
// 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