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

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

问题描述

我们有一个单一线程调用的函数(我们称之为主线程)。在函数体内,我们产生多个工作线程来做CPU密集型工作,等待所有线程完成,然后在主线程上返回结果。



结果



到目前为止都很好用。

/ p>

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



我们如何做 b

  • 在我们的工作线程上捕获各种异常(std :: exception和一些我们自己的异常)。

  • 记录异常的类型和消息。 li>
  • 在主线程上有一个相应的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< Thread exited with exception:< ex.what()<< \\\
    ;
    }
    }

    return 0;
    }

    因为在你的情况下你有多个工作线程,



    请注意,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 the 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天全站免登陆