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

本文关键字:线程 捕获异常 前线 | 更新日期: 2023-09-27 17:57:07

我的情况是:

从主线程我开始线程 A。在主线程中有一些时间(true)运行了很多时间。其中是耗时的操作:

    static void Main(string[] args)
    {
        new Thread(Go).Start();
        while (true)
        {
            Thread.Sleep(1000);
        }
    }
    private static void Go()
    {
    }

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

我读了一些文章,例如这篇文章:捕获在不同线程中抛出的异常

唯一的答案是:使用共享变量(答案之一)

因此,解决方案:

    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 调用委托,则不能在循环时切断,因为它是其他线程。事件也是如此。

我该如何处理这个问题?

谢谢

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

实现此目的的最佳方法是使用任务并行库。如果使用 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;
    }
}

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