Thursday, January 05, 2017

No locks is best locks

I learnt about the async/await thing in C# today. It tries to simplify multithreaded programming but there are still all the usual gotchas. If you're just doing something simple like writing a web server or whatever it probably does help a fair bit. For complicated stuff I think a message-passing design with minimal synchronization apart from the message queues is going to be easier to reason about and get right.
private void NormalMethod()
{
Task.Run(() => TestAsync()); // runs the task on the threadpool
}
private async void TestAsync()
{
Console.WriteLine("01. Starting test async");
await T1(); // T1 will return a Task when (if) it hits its first blocker. await will then pause execution of this method until the Task completes.
Console.WriteLine("03. Continuing test async"); // We then resume execution of this method with the same context (locals, callstack, etc.) as before (but maybe on a different physical thread)
await T2();
Console.WriteLine("05. Finished synched async");
T3(); // starts executing T3. When T3 gets to its first await, it will return here (and T3 will keep executing on another thread when the await finishes)
Console.WriteLine("06. Continuing test async");
T4(); // You can only "await" Task objects, nothing else, so async void methods are like orphaned threads in that you can't "join" (wait for them to finish).
Console.WriteLine("07. Finished unsynched async");
}
private async Task T1()
{
await Task.Delay(100);
Console.WriteLine("02. T1");
}
private async Task T2()
{
await Task.Delay(100);
Console.WriteLine("04. T2");
}
private async void T3()
{
await Task.Delay(200);
Console.WriteLine("09. T3");
}
private async void T4()
{
await Task.Delay(100);
Console.WriteLine("08. T4");
}
/*
output:
01. Starting test async
02. T1
03. Continuing test async
04. T2
05. Finished synched async
06. Continuing test async
07. Finished synched async
08. T4
09. T3
*/

No comments: