C# 当发生异常时,如何打破任务链?

C# 当发生异常时,如何打破任务链?,c#,.net,multithreading,task,multitasking,C#,.net,Multithreading,Task,Multitasking,我创造了作品的链条。它们将在我的附加线程中工作。我使用这个任务就是为了这个目的。此外,如果发生任何异常,我希望中断链的工作,并将其抛出调用线程。但是我看到我的链条没有断,act2和act3也完成了 我怎样才能修好它 您必须使用“无故障任务继续”选项 由于使用Flags属性修饰,因此可以将NotFaulted与其他选项组合 var awaiter = task.ContinueWith(_ => act2(), TaskContinuationOptions

我创造了作品的链条。它们将在我的附加线程中工作。我使用这个任务就是为了这个目的。此外,如果发生任何异常,我希望中断链的工作,并将其抛出调用线程。但是我看到我的链条没有断,act2和act3也完成了

我怎样才能修好它


您必须使用“无故障任务继续”选项

由于使用Flags属性修饰,因此可以将NotFaulted与其他选项组合

 var awaiter = task.ContinueWith(_ => act2(),
                TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.NotOnFaulted)
                .ContinueWith(_ => act3(),
                TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.NotOnFaulted)
                .GetAwaiter();

即使您使用的是async/await关键字,这种方法仍然有效,但是您摆脱了GetAwaiter调用。

代码试图以一种非常规的方式使用任务,就像它们是线程一样。它们不是-任务是一个调度在线程池线程上运行的作业,而不是线程本身。调用Task.Start不会执行任何操作,它将安排其委托在线程上运行。这就是为什么从不使用构造函数创建任务

启动和协调任务的最简单方法是使用Task.Run和async/await,例如:

在任务上调用.Wait或.Result会重新调用任务中引发的任何异常

如果没有async/await,则需要使用ContinueWith并实际检查上一个任务的结果。如果您只是想停止处理,可以传递TaskContinuationOptions.NotOnFault:

var result = Task.Run(()=>act1())
                 .ContinueWith( t1=>act2(),TaskContinuationOptions.NotOnFaulted)
                 .ContinueWith( t2=>act3(),TaskContinuationOptions.NotOnFaulted)
                 .Result;

您不需要直接访问等待者。对.Result的最后一次调用将返回整数结果,如果前面的一个任务出现故障,则会引发AggregateException

为什么不直接使用async/await?您不需要任务。启动或直接访问等待者。此外,如果要使用ContinueWith,则需要访问任务以检查异常,例如-ContinueWitht=>if t.Faulted{..}else act3;我通过一本书学习如何处理线程\任务。我仍然没有读到有关async/await的内容。我建议您查看有关如何正确使用的文档示例,例如ContinueWith和TasFactory.StartNew或Task.Run,如果您不想使用async/await。还要检查Task.Result和Task.Wait-do-如果任务出错,它们会抛出。您的代码太复杂了,并且试图公开它不需要的实现内部。在这种情况下,act2没有发布,但act3仍然发布。哦。。。如果我将TaskContinuationOptions.NotOnConceled与TaskContinuationOptions.NotOnFault一起添加,则其工作方式与我预期的一样。非常感谢。请尝试AttachedToParent标志。请注意,如果使用ExecuteSynchronously标志,则实际上并没有使用任务的真正威力。使用ContinueWith方法是常规方法。我同意您的看法,async/await更干净、更易于维护,但使用Start/GetAwaiter/GetResults并没有什么错。最后,async/await只是这些方法的语法糖分。@MatteoMarciano MSCP这些方法仅在WinRT中是必需的,WinRT没有任务。没有其他运行时需要它们。至于为什么使用它们是错误的,代码的复杂性是显而易见的。代码最终变得复杂得多,没有任何好处。您可以找到Task.Start的唯一位置是“问题”,因此在某些情况下仍然需要继续使用。关于WinRT不支持任务,这并不完全正确。也许你说的是WinRT组件。我没说不使用延续。我说等待者不被使用
public static async Task<int> MyMethodAsync()
{
    try
    {
        await Task.Run(()=>act1());
        await Task.Run(()=>act2());
        var result=await Task.Run(()=>act3());
        return result;
    }
    catch (Exception exc)
    {
           //Do something
    }
}
var result=MyMethodAsync().Result;
var result = Task.Run(()=>act1())
                 .ContinueWith( t1=>act2(),TaskContinuationOptions.NotOnFaulted)
                 .ContinueWith( t2=>act3(),TaskContinuationOptions.NotOnFaulted)
                 .Result;