SpiritBob
SpiritBob

Reputation: 2702

TaskContinuations ran synchronously with async lambdas

If we have a a a task, and for that task we create a continuation (via ContinueWith), with TaskContinuationOptions.RunSynchronously, if the method being executed in ContinueWith is the following:

static async Task SimpleMethodContinuationAsync(Task antecedentTask, object state)
{
    // some very lightweight, thread-safe synchronous code.
    await Task.Delay(5000); // Simulate async work.
    // continuation of some more very lightweight, thread-safe synchronous code.
}

The part after the await - will it effectively release the thread that started executing the task continuation? And on which thread will the rest of this continuation resume?

The question is asked when there is no SynchronizationContext present for the antecedent task of the continuation above, but I've heard that SynchronizationContext does not flow through ContinueWith method calls? Is that true?

Upvotes: 0

Views: 338

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 456977

I second Marc's comment: you should avoid ContinueWith; it's a low-level API that has potentially dangerous default behavior.

The part after the await - will it effectively release the thread that started executing the task continuation?

The await will do that, yes.

And on which thread will the rest of this continuation resume? ... The question is asked when there is no SynchronizationContext present for the antecedent task of the continuation above

Most likely, it would be the thread pool thread that completes the Task returned by Task.Delay. This is because await uses TaskContinuationOptions.ExecuteSynchronously (note: this is an implementation detail; do not depend on this behavior).

I say "most likely" because there are situations where ExecuteSynchronously doesn't execute synchronously. It's an optimization hint, not a requirement. This also applies to the part of your continuation before the await: it is most likely (not definitely) running on the thread that completed the antecedent task.

but I've heard that SynchronziationContext does not flow through ContinueWith method calls? Is that true?

ContinueWith works at the task level. It has some logic for flowing through TaskScheduler.Current (which IMO is one aspect that makes this API dangerous), but has no awareness of SynchronizationContext.

Upvotes: 5

Related Questions