上午。
(尝试做):我试着并行执行几个任务。每个任务使用for循环运行文本文件的某个部分(第一个任务=第1-10行。第二个任务=第11-20行等)。在每行检查结束时,引发一个事件,GUI线程更新UI,即“已检查X行。”
(坚持):我不明白如何做到这一点,但仍然能够正确处理异常。我知道,我需要打电话
task.Wait();
或
task.WaitAll();
但是通过调用它,UI线程就在那里等待,我在任务中触发的任何事件来更新UI只是添加了UI的队列。
有谁知道怎么解决这个问题?
注意:如果这是愚蠢的,我会提前道歉但是我遇到了一些线程问题。
因为任务将所有异常捆绑到AggregateException中并且如果我调用task.Waitall(); UI线程似乎要等到任务完成或抛出异常。
答案 0 :(得分:1)
一种选择是将另一个任务附加到您的任务,作为处理任何异常的“处理程序”。
以下是一个例子:
var task = Task.Factory.StartNew(() =>
{
throw new Exception("oops!");
});
// attach an exception-handling task
task.ContinueWith(previousTask =>
{
// do something with the exception
Console.WriteLine(previousTask.Exception);
}, TaskContinuationOptions.OnlyOnFaulted);
请注意,ContinueWith
附带的任务有TaskContinuationOptions.OnlyOnFaulted
,这意味着它只会在附加的任务抛出异常时运行。
这样,您的异常可以异步处理,您无需等待任何事情。
但是,既然你想做一个并行for循环,我可能会做类似的事情:
Task.Factory.StartNew(() =>
{
try
{
Parallel.For(..., i =>
{
...
});
}
catch (AggregateException e)
{
// handle it somehow
}
});
这样,您的主任务会等待所有子任务,但生成它的UI线程不必等待。
你必须确定的主要事情是你的catch
子句(或前面例子中的处理任务)永远不会引发异常。
答案 1 :(得分:0)
一种替代方法(最简单的方法)是在抛出它的线程中处理异常。
所以你需要在执行方法中尝试catch - 然后你所做的就是你的设计,你可以举例说明一个UI可以处理的错误事件(仍然在异常线程的上下文中)。 / p>
另一个替代方案是你可以将你的任务调度代码(即调用WaitAll()的代码)作为BackgroundWorker启动 - 这将使UI自由地执行它的东西(处理其他输入) - 这可能是更好的方法,但可能需要一些重新分解。