所以我最近被告知我如何使用我的.ContinueWith for Tasks并不是使用它们的正确方法。我还没有在互联网上找到这方面的证据,所以我会问你们,看看答案是什么。以下是我如何使用.ContinueWith:
的示例public Task DoSomething()
{
return Task.Factory.StartNew(() =>
{
Console.WriteLine("Step 1");
})
.ContinueWith((prevTask) =>
{
Console.WriteLine("Step 2");
})
.ContinueWith((prevTask) =>
{
Console.WriteLine("Step 3");
});
}
现在我知道这是一个简单的例子,它运行得非常快,但只是假设每个任务都进行了一些更长的操作。所以,我被告知在.ContinueWith中,你需要说prevTask.Wait();否则你可以在上一个任务完成之前完成工作。这甚至可能吗?我假设我的第二个&第三个任务只有在前一个任务完成后才会运行。
我被告知如何编写代码:
public Task DoSomething()
{
return Task.Factory.StartNew(() =>
{
Console.WriteLine("Step 1");
})
.ContinueWith((prevTask) =>
{
prevTask.Wait();
Console.WriteLine("Step 2");
})
.ContinueWith((prevTask) =>
{
prevTask.Wait();
Console.WriteLine("Step 3");
});
}
答案 0 :(得分:116)
嗯......我认为目前的一些答案缺少一些东西:例外会发生什么?
在延续中调用Wait
的唯一原因是观察延续本身中前因的潜在异常。如果您在Result
的情况下访问Task<T>
,并且手动访问Exception
属性,则会发生相同的观察。
坦率地说,我不会打电话给Wait
或访问Result
,因为如果有例外,您将支付重新加价的费用,这是不必要的开销。相反,您只需检查先行IsFaulted
下的Task
属性即可。或者,您可以通过链接多个同级延续来创建分叉工作流,这些延续只会基于TaskContinuationOptions.OnlyOnRanToCompletion
和TaskContinuationOptions.OnlyOnFaulted
的成功或失败而触发。
现在,没有必要在延续中观察前提的例外情况,但如果“步骤1”失败,您可能不希望工作流程继续前进。在这种情况下:为TaskContinuationOptions.NotOnFaulted
调用指定ContinueWith
会阻止连续逻辑永远触发。
请记住,如果您自己的延续没有观察到异常,那么等待整个工作流程完成的人将成为观察它的人。要么Wait
Task
在{{1}}上游,要么已经自行延续,以了解它何时完成。如果是后者,他们的继续需要使用上述观察逻辑。
答案 1 :(得分:20)
您正确使用它。
创建一个在目标时异步执行的延续 任务完成。
来源:Task.ContinueWith Method (Action as MSDN)
在每个prevTask.Wait()
调用中调用Task.ContinueWith
似乎是一种奇怪的方式来重复不必要的逻辑 - 即做一些“超级确定”,因为你实际上不明白什么是一点点代码呢。就像检查一个null一样只是为了抛出ArgumentNullException
无论如何都会抛出它。
所以,不,谁告诉你这是错的,可能不明白为什么Task.ContinueWith
存在。
答案 2 :(得分:16)
谁告诉过你的?
引用MSDN:
创建在目标时异步执行的延续 任务完成。
此外,如果没有等待上一个任务完成,继续的目的是什么?
您甚至可以自己测试一下:
Task.Factory.StartNew(() =>
{
Console.WriteLine("Step 1");
Thread.Sleep(2000);
})
.ContinueWith((prevTask) =>
{
Console.WriteLine("I waited step 1 to be completed!");
})
.ContinueWith((prevTask) =>
{
Console.WriteLine("Step 3");
});
答案 3 :(得分:5)
Task.Continuewith
上的MSDN
返回的任务将不会被安排执行,直到 当前任务已完成。如果通过指定的标准 continuationOptions参数不符合,延续任务将 取消而不是预定。
我认为你希望它在第一个例子中起作用的方式是正确的方法。
答案 4 :(得分:1)
您可能还想考虑使用Task.Run而不是Task.Factory.StartNew。
Stephen Cleary的blog post和Stephen Toub的post that he references解释了这些差异。在this answer中也有讨论。答案 5 :(得分:0)
通过访问Task.Result
,您实际上正在执行与task.wait
答案 6 :(得分:0)
我将重申许多人已经说过的话,prevTask.Wait()
是不必要的。
有关更多示例,可以转到Chaining Tasks using Continuation Tasks,另一个链接由Microsoft提供了很好的示例。