Calling TaskCompletionSource.SetResult in a non blocking manner

I’ve discovered that TaskCompletionSource.SetResult(); invokes the code awaiting the task before returning. In my case that result in a deadlock. Yes, I have a blog post documenting this (AFAIK it’s not documented on MSDN). The deadlock happens because of two things: There’s a mixture of async and blocking code (i.e., an async method is calling … Read more

Wrapping ManualResetEvent as awaitable task

RegisterWaitForSingleObject will combine waits onto dedicated waiter threads, each of which can wait on multiple handles (specifically, 63 of them, which is MAXIMUM_WAIT_OBJECTS minus one for a “control” handle). So you should be able to use something like this (warning: untested): public static class WaitHandleExtensions { public static Task AsTask(this WaitHandle handle) { return AsTask(handle, … Read more

Do I need to dispose of a Task?

While the normal rule of thumb is to always call Dispose() on all IDisposable implementations, Task and Task<T> are often one case where it’s better to let the finalizer take care of this. The reason Task implements IDisposable is mainly due to an internal WaitHandle. This is required to allow task continuations to work properly, … Read more

How to implement an efficient WhenEach that streams an IAsyncEnumerable of task results?

By using code from this article, you can implement the following: public static Task<Task<T>>[] Interleaved<T>(IEnumerable<Task<T>> tasks) { var inputTasks = tasks.ToList(); var buckets = new TaskCompletionSource<Task<T>>[inputTasks.Count]; var results = new Task<Task<T>>[buckets.Length]; for (int i = 0; i < buckets.Length; i++) { buckets[i] = new TaskCompletionSource<Task<T>>(); results[i] = buckets[i].Task; } int nextTaskIndex = -1; Action<Task<T>> continuation … Read more