C# · 12月 29, 2021

c# – 在继续执行任务时保存异常

我有一个任务< T: Task<A> soMetask = …

此任务可能导致成功,故障或取消.

当任务成功时,我想转换结果,如果不成功则保存结果.

当soMetask引发异常时,这似乎是非常困难的.

我试过的

Task<B> resultTask = StartMyTask().ContinueWith<B>( t => Foo(t.Result),TaskContinuationOptions.OnlyOnRanToCompletion);

如果某些任务发生故障,则会导致resultTask被取消.我想要它的错.

Task<B> resultTask = StartMyTask().ContinueWith<B>( t => Foo(t.Result));

这会导致Visual Studio调试器,因为.Result抛出异常.如果我按F5,resultTask如预期的错误,但它闻起来.

有没有办法让resultTask与soMetask的相同的结果,如果soMetask的错误?

本质上我要做的就是用任务来表达这样的东西:

int F(){ throw new SomeException();}string G(int x){ return x.ToString();}try{ string result = G(F());}catch (SomeException e){ …}解决方法 任务延续是独立的.它们可以用于构建您想要的,但它们不是专门针对该场景设计的.

要问的第一个问题是:关系可以被视为父/子关系(例如,Foo将是StartMyTask的父级)?如果这是有道理的话,那么你可以利用从小孩到家长的状态.

如果将Foo视为“父”,并将StartMyTask视为“小孩”,则设计不成功,那么还有其他选项.连续性对于您需要的是一个低级别(记住,他们只是“在其他任务完成时运行此任务”).

听起来你可能会试图做一些更像“管道”的事情.目前,Rx更适合这种事情.

基于任务的管道并不在这里. ParallelExtensionsExtras library有一个基于任务的管道类,Async CTP有一个TPL数据流库,但目前这两者都不够开发. (例如,Pipeline坚持在独立的线程中运行管道的每个阶段,而Dataflow没有机制可以自动传播异常甚至完成).

所以,如果不能使用Rx,那么我将为任务编写自己的“PipelineTransform”扩展方法,并使用显式TCS来正确处理所有三个完成情况.