C# 是否建议将 prevTask.Wait() 与 ContinueWith(来自 Tasks 库)一起使用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11904821/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is prevTask.Wait() recommended to be used with ContinueWith (from the Tasks library)?
提问by Travyguy9
So I was told recently that how I was using my .ContinueWith for Tasks was not the proper way to use them. I have yet to find evidence of this on the internet so I will ask you guys and see what the answer is. Here is an example of how I use .ContinueWith:
所以最近有人告诉我,我如何使用 .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");
});
}
Now I know this is a simple example and it will run very fast, but just assume each task does some longer operation. So, what I was told is that in the .ContinueWith, you need to say prevTask.Wait(); otherwise you could do work before the previous task finishes. Is that even possible? I assumed my second & third task would only run once their previous task finishes.
现在我知道这是一个简单的例子,它会运行得非常快,但假设每个任务都执行一些更长的操作。所以,我被告知在 .ContinueWith 中,你需要说 prevTask.Wait(); 否则,您可以在上一个任务完成之前完成工作。这甚至可能吗?我假设我的第二个和第三个任务只会在他们上一个任务完成后运行。
What I was told how to write the code:
我被告知如何编写代码:
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");
});
}
采纳答案by Drew Marsh
Ehhh.... I think some of the current answers are missing something: what happens with exceptions?
呃......我认为目前的一些答案缺少一些东西:异常会发生什么?
The only reason you would call Waitin a continuation would be to observe a potential exception from the antecedent in the continuation itself. The same observation would happen if you accessed Resultin the case of a Task<T>and also if you manually accessed the Exceptionproperty.
Frankly, I wouldn't call Waitor access Resultbecause if there is an exception you'll pay the price of re-raising it which is unnecessary overhead. Instead you can just check the IsFaultedproperty off the antecedent Task. Alternatively you can create forked workflows by chaining on multiple sibling continuations that only fire based on either success or failure with TaskContinuationOptions.OnlyOnRanToCompletionand TaskContinuationOptions.OnlyOnFaulted.
您调用Wait延续的唯一原因是在延续本身中观察到来自前件的潜在异常。如果您Result在 a 的情况下访问Task<T>以及手动访问该Exception属性,则会发生相同的观察结果。坦率地说,我不会调用Wait或访问,Result因为如果出现异常,您将付出重新提高它的代价,这是不必要的开销。相反,您可以只检查IsFaultedantecedent的属性Task。或者,您可以通过链接多个同级延续来创建分叉工作流,这些延续仅基于成功或失败与TaskContinuationOptions.OnlyOnRanToCompletion和触发TaskContinuationOptions.OnlyOnFaulted。
Now, it's not necessary to observe the exception of the antecedent in the continuation, but you may not want your workflow to move forward if, say, "Step 1" failed. In that case: specifying TaskContinuationOptions.NotOnFaultedto your ContinueWithcalls would prevent the continuation logic from ever even firing.
现在,没有必要在延续中观察先行词的异常,但是如果“步骤 1”失败,您可能不希望工作流程继续前进。在这种情况下:指定TaskContinuationOptions.NotOnFaulted您的ContinueWith调用将阻止继续逻辑甚至触发。
Keep in mind that, if your own continuations don't observe the exception, the person who is waiting on this overall workflow to complete is going to be the one to observe it. Either they're Waiting on the Taskupstream or have tacked on their own continuation to know when it is complete. If it is the latter, their continuation would need to use the aforementioned observation logic.
请记住,如果您自己的延续没有观察到异常,那么等待整个工作流完成的人将是观察它的人。他们要么Wait在Task上游,要么在自己的延续上进行了跟踪以了解何时完成。如果是后者,它们的延续就需要使用前面提到的观察逻辑。
回答by Anders Arpi
You are using it correctly.
您正在正确使用它。
Creates a continuation that executes asynchronously when the target Task completes.
创建一个在目标任务完成时异步执行的延续。
Source: Task.ContinueWith Method (Action as MSDN)
来源:Task.ContinueWith 方法(作为 MSDN 的操作)
Having to call prevTask.Wait()in every Task.ContinueWithinvocation seems like a weird way to repeat unnecessary logic - i.e. doing something to be "super duper sure" because you actually don't understand what a certain bit of code does. Like checking for a null just to throw an ArgumentNullExceptionwhere it would've been thrown anyway.
必须prevTask.Wait()在每次Task.ContinueWith调用中都调用似乎是一种重复不必要逻辑的奇怪方式 - 即做一些“超级确定”的事情,因为您实际上不了解某段代码的作用。就像检查一个空值只是为了抛出一个ArgumentNullException无论如何都会被抛出的地方。
So, no, whoever told you that is wrong and probably doesn't understand why Task.ContinueWithexists.
所以,不,谁告诉你那是错误的,可能不明白为什么Task.ContinueWith存在。
回答by mclark1129
From the MSDNon Task.Continuewith
从MSDN上Task.Continuewith
The returned Task will not be scheduled for execution until the current task has completed. If the criteria specified through the continuationOptions parameter are not met, the continuation task will be canceled instead of scheduled.
在当前任务完成之前,不会安排返回的任务执行。如果不满足通过 continuationOptions 参数指定的条件,则将取消延续任务而不是计划。
I think that the way you expect it to work in the first example is the correct way.
我认为您期望它在第一个示例中工作的方式是正确的方式。
回答by ken2k
Who told you that?
谁告诉你的?
Quoting MSDN:
引用MSDN:
Creates a continuation that executes asynchronously when the target Task completes.
创建一个在目标任务完成时异步执行的延续。
Also, what would be the purpose of ContinueWith if it wasn't waiting for the previous task to be completed?
另外,如果不是等待上一个任务完成,ContinueWith的目的是什么?
You can even test it by yourself:
你甚至可以自己测试一下:
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");
});
回答by Sameh
By Accessing Task.Resultyou are actually doing similar logic to task.wait
通过访问,Task.Result您实际上正在执行类似的逻辑task.wait
回答by bizcad
You might also want to consider using Task.Run instead of Task.Factory.StartNew.
您可能还需要考虑使用 Task.Run 而不是 Task.Factory.StartNew。
Stephen Cleary's blog postand the Stephen Toub's post that he referencesexplain the differences. There is also a discussion in this answer.
Stephen Cleary 的博客文章和他引用的 Stephen Toub 的文章解释了这些差异。这个答案中也有讨论。
回答by Amit Dash
I will reiterate what many have spoken already, prevTask.Wait()is unnecessary.
我将重申许多人已经说过的话,这prevTask.Wait()是不必要的。
For more examples one can go to Chaining Tasks using Continuation Tasks, yet another link by Microsoft with good examples.
有关更多示例,可以使用 Continuation Tasks转到链接任务,这是 Microsoft 提供的另一个带有很好示例的链接。

