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

匿名 (未验证) 提交于 2019-12-03 02:08:02

问题:

What does this mean and how to resolve it?

I am using TPL tasks.

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()

mscorlib

回答1:

If you create a Task, and you don't ever call task.Wait() or try to retrieve the result of a Task, 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.

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:

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

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



回答2:

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)
  • handle the TaskScheduler.UnobservedTaskException event, and mark it observed (call e.SetObserved() after logging the error)


回答3:

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


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!