我正在尝试创建一个并行的过程,该过程不会阻止我的主线程,但仍会记录错误,以防有例外。最初我有这个代码:
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
的全部要点是我可以控制单位测试中的执行顺序。目前,在单位测试中,原始任务和延续将分别使用不同的任务调度程序-TaskScheduler
和MockTaskScheduler
。(不显示简短的单元测试代码,而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.Exception
和Task.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);