防止在异常情况下使用Task.ContinueWith

5
我正在尝试防止任务在第一部分失败后继续进行。
我的代码如下:
Task listener = Task.Factory.StartNew(openConnection).ContinueWith((t) => listenForNumber());

    void openConnection()
    {
        try
        {
           //stuff
        }
        catch
        {
          //morestuff
        }
    }

    void listenForNumber()
    {
       //even more stuff
    }

现在,如果 openConnection() 进入 catch 块,就不应该执行 listenForNumber()。
我尝试使用 ContinueWith((t) => listenForNumber(),TaskContinuationOptions.NotOnFaulted);,但没有成功,需要帮助吗? :(
谢谢。

3
在该catch块中,您是重新抛出异常还是将其吞掉? - Lasse V. Karlsen
3个回答

8

TaskContiuationOptions.NotOnFaulted显然只有在你的方法出现故障(即执行期间抛出未处理的异常)时才会起作用。

在catch块中,您应该使用throw;语句重新引发异常(并保留堆栈跟踪),在执行工作(可能是一些清理工作)之后 - 否则异常不会再次被抛出,因此您的方法将不被视为“已故障”。


好的,但如果我重新抛出异常,最好在哪里(以及如何)吞咽它,以便我不会得到AggregatedExeption或用户代码未处理的异常?我不需要再次处理它,因为在第一个catch块中已经完成了所有操作。 - Ekoms
据我所知,只有在访问任务的 “Result” 属性时才会抛出 AggregateException 异常。这应该是你可以吞掉异常的唯一位置,但首先你应该检查它是否真的是你想要吞掉的异常,而不仅仅是一些意外的异常。 - ShdNx

2
创建一个扩展方法助手。
public static void PropagateExceptions(this Task task)
{
    if (task == null)
        throw new ArgumentNullException("task");
    if (!task.IsCompleted)
        throw new InvalidOperationException("The task has not completed yet.");

    if (task.IsFaulted)
        task.Wait();
}

在执行任何代码之前,请调用PropagateExceptions()扩展方法。如果任务被取消,该方法还将重新抛出异常。请注意保留HTML标签。
t1.ContinueWith(t => { 
    t.PropagateExceptions();
    listenForNumber(); 
});

1

你需要在任务方法中抛出异常。除非TPL捕获到异常,否则它不知道方法已经失败。

即使如此,你仍然需要为故障情况编写一个继续方法。这可以是一个简单的记录异常的方法。

如果你没有为异常编写继续方法,当你的任务方法抛出异常时,你的应用程序将会出现未处理的异常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接