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 methods ExtractArchiveAsync()
, 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.
.ContinueWith(_ => CompressArchiveAsync());
is equivalent to:
.ContinueWith(_ =>
{
return CompressArchiveAsync();
});
Notice the return
.
Your second code snippet doesn't compile because ContinueWith
doesn't return a Task<Task>
, but simply a Task
, and there's nothing to unwrap.
The following is bound to a Func<Task, Task>
(a function that takes a Task
and returns a Task
)
_ =>
{
return CompressArchiveAsync();
}
But the following is actually bound to an Action<Task>
(a function that takes a Task
but doesn't return anything):
_ =>
{
CompressArchiveAsync();
}
And the reference to the Task
created by CompressArchiveAsync
is never returned. Without a reference to it, you can't check the Task
's status.
Note that:
ContinueWith<TResult>(Func<Task, TResult>)
returns a Task<TResult>
ContinueWith(Action<Task>)
returns a Task
. Therefore your ContinueWith(Func<Task, Task>)
returns a Task<Task>
that you can unwrap, but your ContinueWith(Action<Task>)
simply returns a Task
.
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:
_ => CompressArchiveAsync()
Is equivalent to this Statement Lambda:
_ => { return CompressArchiveAsync(); }
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 a Task
.
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:
async Task CompleteBackup()
{
await backup.BackupCurrentDatabaseAsync()
await CompressArchiveAsync());
await .....
}
In the first example, you are calling ContinueWith
with a Func
. Therefore, it will return a Task<T>
. The second try will call the ContinueWith
overload with an Action
, because... well it's an action, it does not return anything. So it will return a simple Task
without T
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.