假设我们有2个工作函数:
void Step1(); // Maybe long.
void Step2(); // Might be short clean up of step 1.
我经常看到:
Task.Run(() => Step1()).ContinueWith(t => Step2());
创建系列中运行的 2个任务。 当:
Task.Run(() => { Step1(); Step2(); });
创建单一任务,运行系列中的2个功能,可能看起来是SIMPLER的选择。
是否有常识性指南可用于确定何时对更简单的方法采取延期的要求?
上面的例子没有异常处理 - 异常处理会对这些指南产生什么影响呢?
答案 0 :(得分:6)
是否有可用于确定的常识指南 什么时候对更简单的方法需要延续?
ContinueWith
使您能够通过TaskContinutationOptions
仅在某些条件下调用Step2
,例如OnlyOnCanceled
OnlyOnFaulted
,OnlyOnRanToCompletion
, 和更多。这样,您就可以构建适合每种情况的工作流程。
您也可以使用一个Task.Run
和一个try-catch
执行此操作,但这可能更适合您维护。
就我个人而言,我试图避免使用ContinueWith
,因为我发现async-await
更简洁,更像是同步。我希望在await
内try-catch
。
答案 1 :(得分:3)
我认为有两个主要原因:
ContinueWith
方法允许您轻松编写许多不同的任务,并使用辅助方法来构建“延续树”。将此更改为命令性调用限制了这一点 - 它仍然可行,但任务比命令式代码更易于组合。
在ContinueWith
案例中,即使Step2
抛出,Step1
也会一直运行。当然,这可以使用try
子句进行模拟,但这有点棘手。最重要的是,它不构成,并且它不能很好地扩展 - 如果你发现你必须运行多个步骤,每个步骤都有自己的错误处理,那么你将很难与进行大量的 try-catch
ES。当然,Task
并不是解决这个问题的唯一方法,也不一定是最好的 - 错误monad也可以让你轻松地构成相互依赖的操作。
答案 2 :(得分:3)
通常,使用最少量的延续。它们使代码和性价比变得混乱。
执行此操作的一个原因是异常行为。即使第一个任务失败,继续也会运行。在这里,据我所知,没有错误行为。在这段特殊的代码中,这似乎不是问题。你会以某种方式需要处理来自Spyder
的异常。
通常,人们都在想“我有一条管道!”并将管道分解为步骤。这是很自然的想法。但是,管道步骤不一定需要以延续的形式表现出来。它们只能是有序的方法调用。
答案 3 :(得分:1)
ContinueWith
), t.Exception
也会运行。
在ContinueWith
语句中,finally
可视为异步try..catch
。这正是使它有用的原因。你也可以在调用ContinueWith
时细粒度。
答案 4 :(得分:0)
是否有可用于确定的常识指南 什么时候对更简单的方法需要延续?
您最有可能使用ContinueWith
当您:
在以下情况下,您可能会使用更简单的方法:
答案 5 :(得分:0)
首先,我假设你需要做异步工作:
public async void Step1(){ /* bla*/ }
public async void Step2(){ /* bla*/ }
然后打电话应该是:
public async void taskRunner(){
await Task.Run(() => { await Step1(); await Step2(); });
}
在第二位确保它将像Continue with
一样工作,你必须添加异常处理(即使第一个任务以异常结束,也始终执行第二个任务。
public async void taskRunner(){
await Task.Run(() => {
try{
await Step1();
}catch(Exception e){
}
await Step2();
});
}
另一点是任务可以是lambdas,因此他们可以只获取先前的任务结果并将其解压缩到下一个任务中,如果没有ContinueWith
则需要额外的变量:
double[] nums = { 3,5,2,6,5,4,3 };
await Task.Run(() => { //still missing exception handling here ;)
double result = await GetSum( nums);
await SubtractValue(nums, result);
});
使用ContinueWith
double[] nums = { 3,5,2,6,5,4,3 };
await Task.Run( () => await GetSum(nums))
.ContinueWith( t => await SubtractValue(nums, t.Result));
在这种特殊情况下,没有语法增益,但是如果没有ContinueWith的帮助,可能会有更复杂的例子,这是不可行的:
另外值得注意的是,编译器足够智能,可以在两种不同的情况下优化代码,因此您必须选择(除非您需要特定的行为),这对您来说更清晰。
我希望我没有犯错,我没有检查代码是否编译,对不起,但是迟到了,明天我会更正答案,以防万一。