简体   繁体   English

在不同线程中引发当前线程时捕获异常

[英]Catch exception in current thread when it's thrown in different thread

My situation is: 我的情况是:

from main thread i start thread A. In main thread there some while(true) which run a lot of time. 从主线程开始,我启动线程A。在主线程中,有一些while(true)运行很多时间。 Inside of while is time consumption operations: 时间消耗内部是:

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

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

    private static void Go()
    {
    }

I wish generate exception in main thread if something go wrong in thread A 如果线程A中出现问题,我希望在主线程中生成异常

I read some articles, for example this one: catch exception that is thrown in different thread 我读了一些文章,例如这篇文章: 捕获在不同线程中引发的异常

and the only answer is: using shared variable ( one of answers ) 唯一的答案是:使用共享变量( 答案之一

So, solution: 因此,解决方案:

    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;
    }

is unacceptable, because i wish get exception ASAP. 是不可接受的,因为我希望尽快获得例外。 Not wait for loop cycling. 不等待循环循环。 For example, if i do cook cookies in while loop, i do not want wait for next cycle when i heat out: when heater is broken i wish in same moment generate exception in main thread. 例如,如果我确实在while循环中烹饪饼干,我不希望在加热时等待下一个周期:当加热器坏了时,我希望在同一时刻在主线程中生成异常。

Now, i can not pass delegates to thread: if i call delegate from thread A, is can not cut while loop, because it other thread. 现在,我无法将委托传递给线程:如果我从线程A调用委托,则无法在while循环中剪切,因为它是其他线程。 Same thing about events. 事件也是一样。

How can i handle this problem? 我该如何处理这个问题?

Thanks 谢谢

The best way to achieve this is using the Task Parallel Library. 实现此目的的最佳方法是使用任务并行库。 If you start your task with TaskCreationOptions.LongRunning , a new thread will be created for the execution of the body of the task. 如果使用TaskCreationOptions.LongRunning启动任务, TaskCreationOptions.LongRunning创建一个新线程来执行任务主体。 You can then either access Task<T>.Result or call Wait from the main thread, and the exception (if any) will be propagated back to the thread. 然后,您可以访问Task<T>.Result或从主线程调用Wait ,并且该异常(如果有)将传播回该线程。 Use a CancellationTokenSource to support cancellation of other operations that are executing concurrently with the Go operation. 使用CancellationTokenSource支持取消与Go操作同时执行的其他操作。

In the following example, calls to Thread.Sleep are placeholders for application-specific time consuming operations. 在以下示例中,对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;
    }
}

As some of the related questions suggest, use a BackgroundWorker. 正如一些相关问题所建议的那样,请使用BackgroundWorker。 If the worker thread raises an exception, it gets passed to the main thread via the RunWorkerCompleted event. 如果辅助线程引发异常,它将通过RunWorkerCompleted事件传递给主线程。 See http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.runworkercompleted(v=vs.110).aspx . 请参阅http://msdn.microsoft.com/zh-cn/library/system.componentmodel.backgroundworker.runworkercompleted(v=vs.110).aspx

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM