如何生成任务以解包

有人可以解释这两个陈述之间的区别:

Task bTask = backup.BackupCurrentDatabaseAsync() .ContinueWith(_ => CompressArchiveAsync()); //unwrap the tasks to produce one entire task Task t = bTask.Unwrap(); 

VS

 Task bTask = backup.BackupCurrentDatabaseAsync() .ContinueWith(_ => { CompressArchiveAsync(); }); //unwrap the tasks to produce one entire task Task t = bTask.Unwrap(); 

ExtractArchiveAsync()BackupCurrentDatabaseAsync()RestoreDatabaseAsync()都返回一个Task

这里,第一个Continuation返回一个Task 。 然后我可以Unwrap()这个任务,将Continuations放在结果(内部)任务上。

第二个版本不编译。 这里唯一不同的是CompressArchiveAsync()周围的大括号。

我试图访问结果(内部) Task以检查Task.Status 。 如果我使用第二种方法,Task.Status将报告BackupCurrentDatabaseAsync()任务的结果。

 .ContinueWith(_ => CompressArchiveAsync()); 

相当于:

 .ContinueWith(_ => { return CompressArchiveAsync(); }); 

注意return

你的第二个代码片段没有编译,因为ContinueWith没有返回Task ,只是一个Task ,而且没有什么可以解包。

以下内容绑定到Func (一个接受Task并返回Task的函数)

 _ => { return CompressArchiveAsync(); } 

但是以下实际上绑定到Action (一个接受Task但不返回任何内容的函数):

 _ => { CompressArchiveAsync(); } 

并且永远不会返回由CompressArchiveAsync创建的Task的引用。 如果没有引用它,则无法检查Task的状态。

注意:

  • ContinueWith(Func)返回一个Task
  • ContinueWith(Action)返回一个Task

因此,您的ContinueWith(Func)返回一个可以解包的Task ,但您的ContinueWith(Action)只返回一个Task

不同之处在于Lambda Expression语法。

Lambda有两种类型: Expression LambdasStatement Lambdas 。 表达式Lambda没有大括号并返回表达式的结果,而Statement Lambdas具有包含零个或多个语句的大括号(其中一个可以是return语句)。

所以这个Expression Lambda:

 _ => CompressArchiveAsync() 

相当于本声明Lambda:

 _ => { return CompressArchiveAsync(); } 

所以,区别在于,在第一个延续中你返回一个任务,但在第二个你不是,它只是一个无效的匿名代表。 这就是为什么第一个延续是一个Task而第二个继续是一个Task

长评显示4.5代码。

如果你可以移动到.Net 4.5,那么你试图编写的代码可以用async / await以更紧凑的方式重写,这实际上是在内部实现所有代码:

  async Task CompleteBackup() { await backup.BackupCurrentDatabaseAsync() await CompressArchiveAsync()); await ..... } 

在第一个示例中,您使用Func调用ContinueWith 。 因此,它将返回Task 。 第二次尝试将使用Action调用ContinueWith重载,因为……好吧它是一个动作,它不会返回任何内容。 所以它将返回一个没有T的简单Task