通过等待任务或访问它的Exception属性,没有观察到任务的exception。 结果,没有被察觉的例外是
这是什么意思,如何解决?
我正在使用TPL任务。
整个错误
通过等待任务或访问它的Exception属性,没有观察到任务的exception。 结果,终结者线程重新抛出了未观察到的exception。
在System.Threading.Tasks.TaskExceptionHolder.Finalize()
mscorlib程序
如果你创build了一个Task,并且你不曾经调用task.Wait()
或者试图获取Task<T>
的结果,那么当垃圾收集器收集任务时,它将在定稿过程中拆除你的应用程序。 有关详细信息,请参阅TPL中“exception处理”的 MSDN页面。
这里最好的select是“处理”exception。 这可以通过延续完成 – 你可以附加一个延续任务,并logging/吞下/等发生的exception。 这提供了一个干净的方式来logging任务exception,可以写成一个简单的扩展方法,即:
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); }
通过以上这些,您可以防止任何任务将应用程序拆除,并通过以下方式将其logging下来:
Task.Factory.StartNew( () => { // Do your work... }).LogExceptions();
或者,您可以订阅TaskScheduler.UnobservedTaskException并在那里处理它。
当然; 这意味着一个Task
被留在垃圾收集后被敲定,但任务本身失败。 有两个修复程序:
- 处理任务直接失败(使用
ContinueWith(...)
进行预订,并在参数中检查Task
中的.IsFaulted
和.Exception
) - 处理
TaskScheduler.UnobservedTaskException
事件,并将其标记为已logginge.SetObserved()
logging错误后调用e.SetObserved()
)
试试这个:
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; }