Skip to content

Instantly share code, notes, and snippets.

@vasilkosturski
Last active June 3, 2022 13:03
Show Gist options
  • Save vasilkosturski/ddfcd255f2f67d800b5a136fcafb4fa4 to your computer and use it in GitHub Desktop.
Save vasilkosturski/ddfcd255f2f67d800b5a136fcafb4fa4 to your computer and use it in GitHub Desktop.
using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
namespace StateMachineConceptual
{
class Program
{
static async Task Main()
{
var res = await MyAsyncMethod(500, 1000);
Console.WriteLine(res);
}
private static Task<int> MyAsyncMethod(int firstDelay, int secondDelay)
{
var stateMachine = new MyAsyncMethodStateMachine(firstDelay, secondDelay, 0);
stateMachine.MoveNext();
return stateMachine.ResultTask;
}
private class MyAsyncMethodStateMachine
{
private readonly TaskCompletionSource<int> _taskBuilder = new TaskCompletionSource<int>();
private readonly int _firstDelay;
private readonly int _secondDelay;
private int _state;
private TaskAwaiter _awaiter;
public MyAsyncMethodStateMachine(int firstDelay, int secondDelay, int initialState)
{
_firstDelay = firstDelay;
_secondDelay = secondDelay;
_state = initialState;
}
public void MoveNext()
{
try
{
if (_state == 0)
{
Console.WriteLine("Before first await.");
_state = 1;
_awaiter = Task.Delay(_firstDelay).GetAwaiter();
if (!_awaiter.IsCompleted)
{
_awaiter.OnCompleted(MoveNext);
return;
}
}
if (_state == 1)
{
_awaiter.GetResult();
Console.WriteLine("Before second await.");
_state = 2;
_awaiter = Task.Delay(_secondDelay).GetAwaiter();
if (!_awaiter.IsCompleted)
{
_awaiter.OnCompleted(MoveNext);
return;
}
}
Console.WriteLine("Done.");
_taskBuilder.SetResult(42);
}
catch (Exception ex)
{
_taskBuilder.SetException(ex);
}
}
public Task<int> ResultTask => _taskBuilder.Task;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment