C# 如何生成任务<;任务>;拆开

C# 如何生成任务<;任务>;拆开,c#,.net,task-parallel-library,async-await,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(); Task bTask=backup.BackupCurrentDatabaseAsync() .C

有人能解释一下这两种说法的区别吗

Task<Task> bTask = backup.BackupCurrentDatabaseAsync()
    .ContinueWith(_ => CompressArchiveAsync());
//unwrap the tasks to produce one entire task
Task t = bTask.Unwrap();
Task bTask=backup.BackupCurrentDatabaseAsync()
.ContinueWith(=>CompressArchiveAsync());
//展开任务以生成一个完整的任务
Task t=bTask.Unwrap();
vs

Task bTask=backup.BackupCurrentDatabaseAsync()
.ContinueWith(=>
{
CompressArchiveAsync();
});
//展开任务以生成一个完整的任务
Task t=bTask.Unwrap();
方法
ExtractArchiveAsync()
BackupCurrentDatabaseAsync()
RestoreDatabaseAsync()
都返回一个
任务

.ContinueWith(_ => CompressArchiveAsync());
这里,第一个延续返回一个
任务
。然后,我可以
Unwrap()
此任务以在结果(内部)任务上放置延续

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


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

区别在于Lambda表达式语法

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

所以这个表达式Lambda:

_ => CompressArchiveAsync()
等同于此语句Lambda:

_ => { return CompressArchiveAsync(); }
所以,不同之处在于,在第一个继续中,您返回一个任务,但在第二个继续中,您没有返回,它只是一个无效的匿名委托。这就是为什么第一个continuation是一个
任务
,而第二个continuation只是一个
任务

.ContinueWith(_ => CompressArchiveAsync());
相当于:

.ContinueWith(_ => 
{
    return CompressArchiveAsync();
});
请注意返回的

您的第二个代码段未编译,因为
ContinueWith
不会返回
任务
,而只返回
任务
,并且没有任何可展开的内容

以下内容绑定到
Func
(接受
任务
并返回
任务
的函数)

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

并且从不返回由
CompressArchiveAsync
创建的对
任务的引用。如果没有对它的引用,则无法检查
任务的状态

请注意:

  • 返回一个
    任务
  • 返回一个
    任务

因此,您的
ContinueWith(Func)
返回一个可以展开的
Task
,但是
ContinueWith(Action)
只返回一个
Task

在第一个示例中,您使用
Func
调用
ContinueWith
。因此,它将返回一个
任务
。第二次尝试将调用带有
操作的
ContinueWith
重载,因为。。。这是一个动作,它不会返回任何东西。因此,它将返回一个简单的
任务
,不带
T

长注释,以显示4.5代码

.ContinueWith(_ => CompressArchiveAsync());
如果您可以迁移到.Net 4.5,那么您尝试编写的代码可以通过async/await以更紧凑的方式重写,async/await本质上是在内部实现所有代码:

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

边注:如果可能的话,考虑移动到4.5和异步/ AWAT。将产生更容易阅读的代码…不幸的是仍然在4!如何在4.5中实现上述功能?
async
/
wait
是C#5.0的主要功能。虽然它只在针对.NET 4.5时起到开箱即用的作用,但您可以使用异步目标包。感谢Alexei,如果我有与我的
ContinueWith()相关联的
TaskContinuationOptions
,这个方法会更详细吗?@Simon如果你需要对任务进行非常详细的控制,你可能仍然需要直接使用
ContinueWith
和类似的调用。我没有这样做,所以没有直接的建议。@Simon:我建议你使用这个基于
wait
的代码。通过安装,您可以将其与.NET 4.0桌面一起使用。使用
await
,已经提供了所有适当的
TaskContinuationOptions
,并且不需要那种级别的控制。@Stephen Cleary-谢谢,我将听取任务主管的建议:async/await是C#5特性(它的目标是.NET4.5+,但正如StephenCleary所提到的,它也可以与该包一起在.NET4.0上使用)
 async Task CompleteBackup()
 {
    await backup.BackupCurrentDatabaseAsync()
    await CompressArchiveAsync());
    await .....
 }