我有以下代码
var exceptions = new ConcurrentQueue<Exception>();
Task task = Task.Factory.StartNew(() =>
{
try
{
Parallel.Invoke(
async () => await _aViewModel.LoadData(_someId),
async () => await _bViewModel.LoadData(_someId)
);
}
catch (Exception ex)
{
exceptions.Enqueue(ex);
}
}).ContinueWith((continuation) =>
{
if (exceptions.Count > 0) throw new AggregateException(exceptions);
});
我在这里使用 Task.StartNew,因为 LoadData 方法使用 Dispatcher.StartAsync 方法在内部调用主 UI 线程。
我遇到的问题是,如果我强制 _aViewModel.LoadData
抛出异常,它不会在 Catch(Exception) 子句中捕获(如果我捕获 AggregateException 也不会)。我不明白为什么!?
最佳答案
Parallel.Invoke
不是async
感知的。所以你的 async
lambdas 被转换为 async void
方法,这些方法具有非常尴尬的错误语义(它们不允许离开 async void
方法; 相反,它们被捕获并直接在 SynchronizationContext
上重新引发,该 SynchronizationContext
在 async void
方法启动时处于事件状态 - 在本例中为线程池)。/p>
我不确定您为什么首先使用 Parallel.Invoke
。由于您的方法已经是 async
,您可以这样做:
Task task = Task.Factory.StartNew(async () =>
{
try
{
Task.WaitAll(
_aViewModel.LoadData(_someId),
_bViewModel.LoadData(_someId)
);
}
catch (Exception ex)
{
exceptions.Enqueue(ex);
}
})...
附言如果您有时间,请重新考虑整个代码部分的结构。 Dispatcher.StartAsync
是一种代码味道。 UI 应该(异步地)请求数据;数据检索对象不必知道 UI。
关于c# - 任务内 Parallel.Invoke 中的异常处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19793771/