Say I have a Task
that generates an int
, and a callback that accepts an int
:
Task<int> task = ...;
Action<int> f = ...;
Now I want to set it up so that once the task has completed and returned its integer result, the callfack f
will be called with that integer – without requiring the main thread to wait for the task to complete:
As I understand it, the typical solution for this is the Task.ContinueWith
method:
task.ContinueWith(t => f(t.Result));
However, one could also get a TaskAwaiter
for the task, and use its event-like interface:
TaskAwaiter<int> awaiter = task.GetAwaiter();
awaiter.OnCompleted(() => f(awaiter.GetResult()));
Now, I realize that TaskAwaiter
is not intended for common use in application code, and mainly exists to be used internally by the await
keyword.
But in order to deepen my understanding of the TPL, I'm wondering:
Is there any practical difference between solutions (1) and (2)?
For example,
One difference is that
task.ContinueWith(t => f(t.Result));
will not capture current synchronization context, and in, for example, UI applications - callback will be executed on thread pool thread. While
TaskAwaiter<int> awaiter = task.GetAwaiter();
awaiter.OnCompleted(() => f(awaiter.GetResult()));
will capture synchronization context, and callback will be executed on UI thread.
Of course you can do the same with ContinueWith
:
task.ContinueWith(r => f(r.Result), TaskScheduler.FromCurrentSynchronizationContext());
But that's not what you used in question. So ways provided in your question are different at least in that regard.
There is also a difference in exception representation, accessing Task.Result
if task has faulted will throw AggregateException
(with one or more exceptions as inner exceptions), while accessing awaiter.GetResult()
will not wrap thrown exception in AggregateException
and will rethrow it as is (and if there were multiple exceptions, like from Task.WhenAll
- all except one will be ignored and just one will be thrown).
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