当它在不同的线程中抛出时,捕获当前线程中的异常

时间:2014-04-07 19:32:13

标签: c# multithreading

我的情况是:

从主线程我启动线程A. 在主线程中有一些(true)运行了很多时间。同时进行时间消耗操作:

    static void Main(string[] args)
    {
        new Thread(Go).Start();

        while (true)
        {
            Thread.Sleep(1000);
        }
    }

    private static void Go()
    {
    }

如果线程A中出现错误,我希望在主线程中生成异常

我阅读了一些文章,例如这篇文章:catch exception that is thrown in different thread

唯一的答案是:使用共享变量(one of answers

所以,解决方案:

    static void Main(string[] args)
    {
        new Thread(Go).Start();

        while (true)
        {
            Thread.Sleep(1000);

            if (_bad)
            {
                throw new Exception();
            }
        }
    }

    private static void Go()
    {
        Thread.Sleep(4000);
        _bad = true;
    }

是不可接受的,因为我希望尽快得到例外。不要等待循环循环。例如,如果我在while循环中做饼干,我不想等待下一个循环,当我加热时:当加热器坏了我希望同时在主线程中产生异常。

现在,我无法将委托传递给线程:如果我从线程A调用委托,则无法切换循环,因为它是其他线程。事件也一样。

我该如何处理这个问题?

由于

2 个答案:

答案 0 :(得分:1)

实现此目标的最佳方法是使用任务并行库。如果使用TaskCreationOptions.LongRunning启动任务,将创建一个新线程来执行任务主体。然后,您可以从主线程访问Task<T>.Result或调用Wait,异常(如果有)将传播回线程。使用CancellationTokenSource来支持取消与Go操作同时执行的其他操作。

在以下示例中,对Thread.Sleep的调用是占位符,用于特定于应用程序的耗时操作。

private static CancellationTokenSource _cancellationTokenSource =
    new CancellationTokenSource();

static void Main(string[] args)
{
    Task longRunning = Task.Factory.StartNew(Go, TaskCreationOptions.LongRunning);
    while (true)
    {
        // Pass _cancellationTokenSource.Token to worker items to support
        // cancelling the operation(s) immediately if the long running
        // operation throws an exception
        Thread.Sleep(1000);

        // this will throw an exception if the task faulted, or simply continue
        // if the task is still running
        longRunning.Wait(0);
    }
}

private static void Go()
{
    try
    {
        Thread.Sleep(4000);
        throw new Exception("Oh noes!!");
    }
    catch
    {
        _cancellationTokenSource.Cancel();
        throw;
    }
}

答案 1 :(得分:0)

正如一些相关问题所示,请使用BackgroundWorker。如果工作线程引发异常,它将通过RunWorkerCompleted事件传递给主线程。请参阅http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.runworkercompleted(v=vs.110).aspx