使用ContinueWith()

时间:2019-05-14 17:08:50

标签: c# asynchronous async-await task task-parallel-library

我正在尝试创建一个并行进程,该进程不会阻塞我的主线程,但是在出现异常的情况下仍然会记录错误。最初我有以下代码:

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始终为null,从而阻止我记录任何异常。

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

1 个答案:

答案 0 :(得分:1)

正如@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);