等待任务或访问其Exception属性都未观察到Task的异常。结果,未观察到的异常是


100

这是什么意思,如何解决?

我正在使用TPL任务。

整个错误

等待任务或访问其Exception属性都未观察到Task的异常。结果,未观察到的异常被终结器线程抛出。

在System.Threading.Tasks.TaskExceptionHolder.Finalize()

mscorlib

Answers:


158

如果创建一个Task,并且您从未调用task.Wait()或尝试检索a的结果Task<T>,则当垃圾收集器收集该任务时,它将在完成过程中关闭您的应用程序。有关详细信息,请参见TPL中 MSDN上有关异常处理的页面。

最好的选择是“处理”异常。这可以通过延续来完成-您可以将延续附加到任务,并记录/吞咽/等发生的异常。这提供了一种记录任务异常的干净方法,并且可以编写为简单的扩展方法,即:

public static void LogExceptions(this Task task)
{
    task.ContinueWith( t =>
    {
         var aggException = t.Exception.Flatten();
         foreach(var exception in aggException.InnerExceptions)
             LogException(exception);
    }, 
    TaskContinuationOptions.OnlyOnFaulted);
}

通过上述操作,您可以通过以下方式阻止任何任务拆解应用程序并对其进行记录:

Task.Factory.StartNew( () => 
   { 
       // Do your work...
   }).LogExceptions();

或者,您可以订阅TaskScheduler.UnobservedTaskException并在那里进行处理。


17
为了增加娱乐性,请Off在您选择的名为四个字母的单词的类中使用静态存根方法,并将其用于包罗万象的延续。有助于消除由于这种特殊异常而导致的一些沮丧情绪。
亚伦诺特,2011年

1
@MonsterMMORPG是-您基本上必须在某个地方捕获或处理异常。只要您在某个地方处理它,您的核心问题就会消失。
Reed Copsey

1
在对ContinueWith进行调用之前,任务是否有可能引发异常?
蒂姆·西尔维斯特

1
@TimSylvester该框架仍将通过延续映射它,即使它发生在“延续”附加之前
Reed Copsey 2012年

32
重要说明:仅对才需要.Net 4.0。默认情况下,异常处理已更改.net 4.5不关闭应用程序在.NET 4.5
i3arnon 2014年

43

当然; 这意味着将Task其留给垃圾收集后完成,但是任务本身失败了。有两个修复程序:

  • 处理任务失败直接(使用ContinueWith(...)订阅,检查.IsFaulted.ExceptionTask在参数)
  • 处理TaskScheduler.UnobservedTaskException事件并标记为已观察到(e.SetObserved()记录错误后调用)

4
+1-另加一项-如果您的继续操作只检查了IsFaulted,则可以使用OnlyOnFaulted继续选项,而无需手动检查...
Reed Copsey

实际上,这发生在我在tpl任务中调用了一个公共静态函数的地方。使用try catch可以解决此问题吗?我真的需要创建另一个任务并等待吗?谢谢
MonsterMMORPG

4
+1需要提及SetObservedon UnobservedTaskExceptionEventArgs
James Webster

-17

试试这个:

public static void ThrowFirstExceptionIfHappens(this Task task)
{
    task.ContinueWith(t =>
    {
        var aggException = t.Exception.Flatten();
        foreach (var exception in aggException.InnerExceptions)
        {
            throw exception; // throw only first, search for solution
        }
    },
    TaskContinuationOptions.OnlyOnFaulted); // not valid for multi task continuations
}

public static Task CreateHandledTask(Action action) 
{
    Task tsk = Task.Factory.StartNew(action);
    tsk.ThrowFirstExceptionIfHappens();
    return tsk;
}

5
它的一个 ??? 你什么意思?您能解释一下到目前为止您的答案对答案有什么贡献吗?
Gert Arnold

您刚刚通过继续创建了一个新任务,该任务将失败并陷入相同的情况。
罗伯·泰勒

这个解决方案似乎有点令人费解。我认为您会无意间隐藏功能而没有任何收获。
Velocitas
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.