在任务期间更新GUI时执行具有异常处理的任务

时间:2012-02-29 09:20:41

标签: c# multithreading c#-4.0

上午。

(尝试做):我试着并行执行几个任务。每个任务使用for循环运行文本文件的某个部分(第一个任务=第1-10行。第二个任务=第11-20行等)。在每行检查结束时,引发一个事件,GUI线程更新UI,即“已检查X行。”

(坚持):我不明白如何做到这一点,但仍然能够正确处理异常。我知道,我需要打电话

task.Wait();  

task.WaitAll();

但是通过调用它,UI线程就在那里等待,我在任务中触发的任何事件来更新UI只是添加了UI的队列。

有谁知道怎么解决这个问题?

注意:如果这是愚蠢的,我会提前道歉但是我遇到了一些线程问题。

因为任务将所有异常捆绑到AggregateException中并且如果我调用task.Waitall(); UI线程似乎要等到任务完成或抛出异常。

2 个答案:

答案 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自由地执行它的东西(处理其他输入) - 这可能是更好的方法,但可能需要一些重新分解。