Can someone please explain the difference between these two statements:
Task<Task> bTask = backup.BackupCurrentDatabaseAsync()
.ContinueWith(_ => CompressArchiveAsync());
//unwrap the tasks to produce one entire task
Task t = bTask.Unwrap();
vs
Task<Task> bTask = backup.BackupCurrentDatabaseAsync()
.ContinueWith(_ =>
{
CompressArchiveAsync();
});
//unwrap the tasks to produce one entire task
Task t = bTask.Unwrap();
The methodsExtractArchiveAsync()
, BackupCurrentDatabaseAsync()
, RestoreDatabaseAsync()
all return a Task
.
Here, the first Continuation returns a Task<Task>
. I can then Unwrap()
this task to put Continuations on the resultant (inner) task.
The second version doesn't compile. The only different here is the braces around the CompressArchiveAsync()
.
I am trying to access the resultant (internal) Task
to check the Task.Status
. If I use the second method, the Task.Status is reporting the result of the BackupCurrentDatabaseAsync()
task.
In the first example, you are calling
ContinueWith
with aFunc
. Therefore, it will return aTask<T>
. The second try will call theContinueWith
overload with anAction
, because... well it's an action, it does not return anything. So it will return a simpleTask
withoutT
.is equivalent to:
Notice the
return
.Your second code snippet doesn't compile because
ContinueWith
doesn't return aTask<Task>
, but simply aTask
, and there's nothing to unwrap.The following is bound to a
Func<Task, Task>
(a function that takes aTask
and returns aTask
)But the following is actually bound to an
Action<Task>
(a function that takes aTask
but doesn't return anything):And the reference to the
Task
created byCompressArchiveAsync
is never returned. Without a reference to it, you can't check theTask
's status.Note that:
ContinueWith<TResult>(Func<Task, TResult>)
returns aTask<TResult>
ContinueWith(Action<Task>)
returns aTask
.Therefore your
ContinueWith(Func<Task, Task>)
returns aTask<Task>
that you can unwrap, but yourContinueWith(Action<Task>)
simply returns aTask
.Long comment to show 4.5 code.
If you could move to .Net 4.5 than code you are trying to write can be rewritten in more compact way with async/await which is essentially implements all that code internally:
The difference is in the Lambda Expression syntax.
There are 2 types of Lambdas: Expression Lambdas and Statement Lambdas. Expression Lambdas have no braces and return the result of the expression while Statement Lambdas have braces containing zero or more statements (one of them can be a
return
statement).So this Expression Lambda:
Is equivalent to this Statement Lambda:
So, the difference is that in the first continuation you are returning a task but in the second you are not, it's just a void anonymous delegate. That's why the first continuation is a
Task<Task>
while the second is just aTask
.