有人可以解释这两个陈述之间的区别:
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();
方法ExtractArchiveAsync()
,BackupCurrentDatabaseAsync()
,RestoreDatabaseAsync()
都返回Task
。
此处,第一个Continuation返回Task<Task>
。然后我可以Unwrap()
这个任务将Continuations放在结果(内部)任务上。
第二个版本没有编译。这里唯一不同的是CompressArchiveAsync()
周围的大括号。
我正在尝试访问结果(内部)Task
来检查Task.Status
。如果我使用第二种方法,Task.Status将报告BackupCurrentDatabaseAsync()
任务的结果。
答案 0 :(得分:11)
.ContinueWith(_ => CompressArchiveAsync());
相当于:
.ContinueWith(_ =>
{
return CompressArchiveAsync();
});
注意return
。
您的第二个代码段无法编译,因为ContinueWith
并未返回Task<Task>
,而只是Task
,并且没有任何内容可以解包
以下内容绑定到Func<Task, Task>
(一个带Task
并返回Task
的函数)
_ =>
{
return CompressArchiveAsync();
}
但是以下内容实际上绑定到Action<Task>
(一个Task
但不返回任何内容的函数):
_ =>
{
CompressArchiveAsync();
}
永远不会返回Task
创建的CompressArchiveAsync
的引用。如果没有引用它,您就无法检查Task
的状态。
请注意:
ContinueWith<TResult>(Func<Task, TResult>)
返回Task<TResult>
ContinueWith(Action<Task>)
会返回Task
。因此,ContinueWith(Func<Task, Task>)
会返回您可以解包的Task<Task>
,但您的ContinueWith(Action<Task>)
只会返回Task
。
答案 1 :(得分:3)
区别在于Lambda Expression语法。
Lambda有两种类型: Expression Lambdas 和 Statement Lambdas 。表达式Lambda没有大括号并返回表达式的结果,而Statement Lambdas具有包含零个或多个语句的大括号(其中一个可以是return
语句)。
所以这个Expression Lambda:
_ => CompressArchiveAsync()
相当于本声明Lambda:
_ => { return CompressArchiveAsync(); }
所以,区别在于,在第一个延续中你返回一个任务,但在第二个你不是,它只是一个无效的匿名代表。这就是为什么第一个延续是Task<Task>
,而第二个继续是Task
。
答案 2 :(得分:2)
长期评论显示4.5代码。
如果您可以转移到.Net 4.5,那么您尝试编写的代码可以使用async / await以更紧凑的方式重写,这实际上是在内部实现所有代码:
async Task CompleteBackup()
{
await backup.BackupCurrentDatabaseAsync()
await CompressArchiveAsync());
await .....
}
答案 3 :(得分:1)
在第一个示例中,您使用ContinueWith
来呼叫Func
。因此,它将返回Task<T>
。第二次尝试会使用ContinueWith
调用Action
重载,因为......它是一个动作,它不会返回任何内容。因此,它会返回一个简单的Task
而不是T
。