It should be careful to use several awaits on same Task.
I have encountered with such situation while trying to use BlockingCollection.GetConsumingEnumerable()
method.
And ends up with this simplified test.
class TestTwoAwaiters
{
public void Test()
{
var t = Task.Delay(1000).ContinueWith(_ => Utils.WriteLine("task complete"));
var w1 = FirstAwaiter(t);
var w2 = SecondAwaiter(t);
Task.WaitAll(w1, w2);
}
private async Task FirstAwaiter(Task t)
{
await t;
//await t.ContinueWith(_ => { });
Utils.WriteLine("first wait complete");
Task.Delay(3000).Wait(); // execute blocking operation
}
private async Task SecondAwaiter(Task t)
{
await t;
Utils.WriteLine("second wait complete");
Task.Delay(3000).Wait(); // execute blocking operation
}
}
I think the problem here is the continuation of a task will execute subscribers on a one thread consequentially.
And if one awaiter execute a blocking operation (such a yielding from BlockingCollection.GetConsumingEnumerable()
) it will block other awaiters and they couldn't continue their work.
I think a possible solution will be to call ContinueWith()
before await a task.
It will break a continuation to two parts and blocking operation will be executed on a new thread.
Can someone confirm or disprove a possibility to await on a task several times. And if it is common then what is a proper way to get around blocking?