3 ms·
To be fair, in C# a function can "opt out" of async-await with Task<T>.Wait()/.Result/.GetAwaiter(). In a way C# will use a mixture of green-ish threads/thread
by rndgermandude 7y ago
To be fair, in C# a function can "opt out" of async-await with Task<T>.Wait()/.Result/.GetAwaiter().
In a way C# will use a mixture of green-ish threads/threads already, in that await-ed calls are either scheduled on a thread worker pool (via a TaskScheduler) or executed synchronously ("inline")... Which comes with it's own set of surprises and gotchas.
async Task<bool> DoSomethingElse() {
// [0] do something long-running
}
async Task DoSomething() {
var otherTask = DoSomethingElse();
// [1] do something long-running
var other = await otherTask;
if (other) {
// do yet another thing
}
}
So, when will [1] run? Before [0], concurrently on another pool thread to [0], or after [0]? The answer is: you cannot really know from the information presented. The compiler might decide that DoSomethingElse is to be called synchronously ("inline", attached child tasks), so before [1] will get a chance to run. Or it might decide to run it concurrently, but then the TaskScheduler might decide it's doing enough of concurrent work already (e.g. every thread in the pool is busy) and run [1] before [0].
This is usually nothing to be concerned about, until it is. Coming from js' world of async-await where a certain order is guaranteed, I footgunned myself in C#... my real-world DoSomethingElse() essentially was a forever-loop that would only terminate on a CancelationToken (basically a "is this canceled" flag) and the compiler decided it should be executed synchronously for me, so [1] never got a chance to run. The fix was Task.Run(DoSomethingElse) btw, thus explicitly not "inline"-ing the call.
https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/attached-and-detached-child-tasks https://docs.microsoft.com/en-us/dotnet/standard/parallel-pr...