如何生成Task <task> to Unwrap </task>

时间:2014-12-17 16:13:59

标签: c# .net task-parallel-library async-await

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

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()任务的结果。

4 个答案:

答案 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(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