任务的异常不是通过等待任务或访问其异常属性来观察的。因此,未观察到的异常是

时间:2022-06-07 02:17:21

What does this mean and how to resolve it?

这意味着什么?如何解决?

I am using TPL tasks.

我正在使用TPL任务。

The whole error

整个错误

A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread.

任务的异常不是通过等待任务或访问其异常属性来观察的。结果,未观察到的异常被终结器线程重新抛出。

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

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

mscorlib

mscorlib

3 个解决方案

#1


130  

If you create a Task, and you don't ever call task.Wait() or try to retrieve the result of a Task<T>, when the task is collected by the garbage collector, it will tear down your application during finalization. For details, see MSDN's page on Exception Handling in the TPL.

如果您创建了一个任务,并且从来没有调用Task . wait()或尝试检索任务 的结果,当垃圾收集器收集该任务时,它将在结束时销毁您的应用程序。有关详细信息,请参阅MSDN在TPL中的异常处理页面。

The best option here is to "handle" the exception. This can be done via a continuation - you can attach a continuation to the task, and log/swallow/etc the exception that occurs. This provides a clean way to log task exceptions, and can be written as a simple extension method, ie:

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

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);
}

With the above, you can prevent any task from tearing down the app, and logging it, via:

有了以上这些,你就可以防止任何任务撕毁app,并通过以下方式记录下来:

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

Alternatively, you can subscribe to the TaskScheduler.UnobservedTaskException and handle it there.

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

#2


32  

Sure; it means a Task got finalized after being left to garbage collection, but the task itself failed. There are two fixes:

确定;这意味着任务在被遗留为垃圾收集之后被完成,但是任务本身失败了。有两个补丁:

  • handle the tasks fail directly (use ContinueWith(...) to subscribe, and check .IsFaulted and .Exception on the Task in the parameter)
  • 直接处理任务失败(使用ContinueWith(…)来订阅,并检查.IsFaulted和.Exception在参数中的任务)
  • handle the TaskScheduler.UnobservedTaskException event, and mark it observed (call e.SetObserved() after logging the error)
  • 处理TaskScheduler。UnobservedTaskException事件,并标记它被观察(记录错误后调用e. setobserve ())))

#3


-13  

Try this one:

试试这个:

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;
}

#1


130  

If you create a Task, and you don't ever call task.Wait() or try to retrieve the result of a Task<T>, when the task is collected by the garbage collector, it will tear down your application during finalization. For details, see MSDN's page on Exception Handling in the TPL.

如果您创建了一个任务,并且从来没有调用Task . wait()或尝试检索任务 的结果,当垃圾收集器收集该任务时,它将在结束时销毁您的应用程序。有关详细信息,请参阅MSDN在TPL中的异常处理页面。

The best option here is to "handle" the exception. This can be done via a continuation - you can attach a continuation to the task, and log/swallow/etc the exception that occurs. This provides a clean way to log task exceptions, and can be written as a simple extension method, ie:

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

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);
}

With the above, you can prevent any task from tearing down the app, and logging it, via:

有了以上这些,你就可以防止任何任务撕毁app,并通过以下方式记录下来:

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

Alternatively, you can subscribe to the TaskScheduler.UnobservedTaskException and handle it there.

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

#2


32  

Sure; it means a Task got finalized after being left to garbage collection, but the task itself failed. There are two fixes:

确定;这意味着任务在被遗留为垃圾收集之后被完成,但是任务本身失败了。有两个补丁:

  • handle the tasks fail directly (use ContinueWith(...) to subscribe, and check .IsFaulted and .Exception on the Task in the parameter)
  • 直接处理任务失败(使用ContinueWith(…)来订阅,并检查.IsFaulted和.Exception在参数中的任务)
  • handle the TaskScheduler.UnobservedTaskException event, and mark it observed (call e.SetObserved() after logging the error)
  • 处理TaskScheduler。UnobservedTaskException事件,并标记它被观察(记录错误后调用e. setobserve ())))

#3


-13  

Try this one:

试试这个:

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;
}