如何在线程之间传播异常? [英] How can I propagate exceptions between threads?

查看:160
本文介绍了如何在线程之间传播异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们有一个线程调用的函数(我们将其命名为主线程)。在函数体中,我们生成多个工作线程来执行CPU密集工作,等待所有线程完成,然后在主线程上返回结果。



结果呼叫者可以天真地使用这个功能,内部使用多个内核。



所有的好东西.. / p>

我们遇到的问题是处理异常。我们不希望工作线程上的异常崩溃应用程序。我们希望调用者能够在主线程上捕获它们。我们必须在工作线程上捕获异常,并将它们传播到主线程,以使它们继续从那里退出。



我们该怎么做?



我可以想到的最好的是:


  1. 在我们的工作线程(std :: exception和我们自己的一些例子中)捕获各种异常。

  2. 记录异常的类型和消息。 li>
  3. 在主线程上有一个相应的switch语句,它会重新启动在线程上记录的任何类型的异常。

这有一个明显的缺点:只支持一些有限的异常类型,每当添加新的异常类型时都需要修改。

解决方案

C ++ 11引入了允许在线程之间传输异常的exception_ptr类型:

 #include< iostream> 
#include< thread>
#include< exception>
#include< stdexcept>

static std :: exception_ptr teptr = nullptr;

void f()
{
try
{
std :: this_thread :: sleep_for(std :: chrono :: seconds(1)) ;
throw std :: runtime_error(要在线程之间传递);
}
catch(...)
{
teptr = std :: current_exception();
}
}

int main(int argc,char ** argv)
{
std :: thread mythread(f);
mythread.join();

if(teptr){
try {
std :: rethrow_exception(teptr);
}
catch(const std :: exception& ex)
{
std :: cerr<< 线程退出例外:<< ex.what()<< \\\
;
}
}

return 0;
}

因为在你的情况下你有多个工作线程,你需要保留一个exception_ptr为每个异常。



请注意,exception_ptr是一个共享的类似ptr的指针,因此您需要至少保留一个exception_ptr指向每个异常,否则将发布。



Microsoft具体:如果您使用SEH异常(/ EHa),示例代码还将传输SEH异常,如访问冲突,可能不是您想要的。


We have a function which a single thread calls into (we name this the main thread). Within the body of the function we spawn multiple worker threads to do CPU intensive work, wait for all threads to finish, then return the result on the main thread.

The result is that the caller can use the function naively, and internally it'll make use of multiple cores.

All good so far..

The problem we have is dealing with exceptions. We don't want exceptions on the worker threads to crash the application. We want the caller to the function to be able to catch them on the main thread. We must catch exceptions on the worker threads and propagate them across to the main thread to have them continue unwinding from there.

How can we do this?

The best I can think of is:

  1. Catch a whole variety of exceptions on our worker threads (std::exception and a few of our own ones).
  2. Record the type and message of the exception.
  3. Have a corresponding switch statement on the main thread which rethrows exceptions of whatever type was recorded on the worker thread.

This has the obvious disadvantage of only supporting a limited set of exception types, and would need modification whenever new exception types were added.

解决方案

C++11 introduced the exception_ptr type that allows to transport exceptions between threads:

#include<iostream>
#include<thread>
#include<exception>
#include<stdexcept>

static std::exception_ptr teptr = nullptr;

void f()
{
    try
    {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        throw std::runtime_error("To be passed between threads");
    }
    catch(...)
    {
        teptr = std::current_exception();
    }
}

int main(int argc, char **argv)
{
    std::thread mythread(f);
    mythread.join();

    if (teptr) {
        try{
            std::rethrow_exception(teptr);
        }
        catch(const std::exception &ex)
        {
            std::cerr << "Thread exited with exception: " << ex.what() << "\n";
        }
    }

    return 0;
}

Because in your case you have multiple worker threads, you will need to keep one exception_ptr for each of them.

Note that exception_ptr is a shared ptr-like pointer, so you will need to keep at least one exception_ptr pointing to each exception or they will be released.

Microsoft specific: if you use SEH Exceptions (/EHa), the example code will also transport SEH exceptions like access violations, which may not be what you want.

这篇关于如何在线程之间传播异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆