There are some interesting examples of custom awaiters in Stephen Toub's Await Anything blog post. I specifically like await task.WithCulture() pattern which I think can be useful in real life. However, I can't think of anything else that possibly cannot be done with TaskCompletionSource.
One interesting field where it might be useful for is switching of execution contexts, like with ControlAwaiter from Stephen's blog or ContextSwitcher from this question. Yet this is not considered a good practice, AFAIU.
It'd be interesting to see some other practical and useful examples of custom awaiters, which still would not harm code readability and maintainability.
There are very few realistic use cases for custom awaiters.
However, there are a handful of examples out there, which seem to fit into one of these categories:
Task for performance reasons. The Windows Store platform exposes its (unmanaged) asynchronous operations with custom awaitables. Another example is Stephen Toub's awaitable wrapper for the specialized Socket asynchronous API used in high-traffic memory-intensive scenarios.ConfigureAwait(false) or the WithCurrentCulture you mentioned.await per event raised. In contrast, tasks can only complete once.Task.Yield also uses a custom awaitable, but it seems to be in a category all its own.
Personally, I avoid custom awaitables. Usually category (1) is only considered as a premature optimization. Category (2) is interesting conceptually but if you explore it out, you'll find that the behavior modifiers don't compose well. Category (3) is also interesting but more controversial IMO because the completion semantics may be surprising.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With