Task.Factory.StartNew() 在使用 ContinueWith() 时不包含异常



我正在尝试创建一个并行的过程,该过程不会阻止我的主线程,但仍会记录错误,以防有例外。最初我有这个代码:

var task = Task.Run(
    () => _db.addData());
task.ContinueWith(continuationTask =>
    {
        if (continuationTask.Exception != null)
        {
            _logger.LogError(continuationTask.Exception, "Failed to log mismatch");
        }
    },
    _taskScheduler);

运行应用程序代码时,_taskScheduler设置为TaskScheduler.Current。运行此操作时,它可以并行正确地执行代码,并且当数据库存在问题时,continuationTask.Exception包含适当的异常消息。

指定TaskScheduler的全部要点是我可以控制单位测试中的执行顺序。目前,在单位测试中,原始任务和延续将分别使用不同的任务调度程序-TaskSchedulerMockTaskScheduler。(不显示简短的单元测试代码,而MockTaskScheduler只是一个自定义实现,使我可以排队和执行任务(

由于Task.Run不以TaskScheduler为参数,因此我尝试将代码更改为

var task = Task.Factory.StartNew(
    () => _db.addData(),
    CancellationToken.None,
    TaskCreationOptions.None,
    _taskScheduler);
task.ContinueWith(continuationTask =>
    {
        if (continuationTask .Exception != null)
        {
            _logger.LogError(continuationTask.Exception, "Failed to log mismatch");
        }
    },
    _taskScheduler);

这使我的测试完美地工作,因为我现在可以控制每个任务的执行时间,因为它们使用了相同的可注射_taskScheduler。但是,当使用TaskScheduler.Current运行应用程序代码时,continuationTask.Exception始终为无效,从而阻止我记录任何例外。

Task.Run填充continuationTask.ExceptionTask.Factory.StartNew没有的原因是有原因的吗?我想念什么吗?

正如评论中提到的@mike zboray所述,我需要在嵌套任务时调用 task.Unwrap().ContinueWith()。仅当将Task.Factory.StartNew()用作Task.Run()自动解开嵌套任务时,这是必要的。

我的最终代码看起来像这样:

var task = Task.Factory.StartNew(
    () => _db.addData(),
    CancellationToken.None,
    TaskCreationOptions.None,
    _taskScheduler);
task.Unwrap().ContinueWith(continuationTask =>
    {
        if (continuationTask .Exception != null)
        {
            _logger.LogError(continuationTask.Exception, "Failed to log mismatch");
        }
    },
    _taskScheduler);

最新更新