这是什么意思以及如何解决它?
我正在使用TPL任务。
整个错误
通过等待任务或访问其Exception属性,未观察到任务的异常。结果,终结器线程重新抛出了未观察到的异常。
在System.Threading.Tasks.TaskExceptionHolder.Finalize()
mscorlib程序
答案 0 :(得分:148)
如果您创建了一个任务,并且您没有调用task.Wait()
或尝试检索Task<T>
的结果,那么当垃圾收集器收集任务时,它将会拆除您的任务最终确定期间的申请。有关详细信息,请参阅Exception Handling in the 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并在那里处理。
答案 1 :(得分:38)
不确定;这意味着Task
在被留给垃圾收集后最终确定,但任务本身失败了。有两个修复:
ContinueWith(...)
订阅,并在参数中的.IsFaulted
上查看.Exception
和Task
TaskScheduler.UnobservedTaskException
事件,并将其标记为已观察(在记录错误后调用e.SetObserved()
)答案 2 :(得分:-15)
试试这个:
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;
}