从线程

时间:2018-03-16 03:59:14

标签: c++ multithreading

参考Catching exception from worker thread in the main thread,我创建了一个工作线程,它将异常抛出到主线程然后终止程序(逻辑是在发生异常时退出程序)。

我似乎没有正确实现它,因为程序不会执行直到调用exit()的行。

示例代码:

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

static std::exception_ptr _exceptionPtr = nullptr;

struct WorkerThread
{
    std::thread thread;

    void doSomething()
    {
        int seconds = 0;
        bool shouldStop = false;

        while(shouldStop == false)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            std::cout << "time passed : " << ++seconds << "seconds" << std::endl;

            if (seconds == 10) // something bad happened 10 seconds later
            {
                try
                {
                    shouldStop = true;
                    throw std::runtime_error("something really bad happened");
                }
                catch (const std::runtime_error &ex)
                {
                    _exceptionPtr = std::current_exception();
                }
            }
        }
    }

    void run()
    {
        thread = std::thread([this] { doSomething(); });
        thread.detach();
    }
};

int main(int argc, char *argv[])
{
    WorkerThread workerThread;

    try
    {
        workerThread.run();
    }
    catch (...)
    {
        if (_exceptionPtr)
        {
            try
            {
                std::rethrow_exception(_exceptionPtr);
            }
            catch (std::runtime_error &ex)
            {
                // terminates program if exception happens
                std::cout << "Program will now exit" << std::endl;
                exit(EXIT_FAILURE); // but program never executes till here
            }
        }
    }

    for (;;)
    {
        // do A
        // do B
        // do C
        // do ...
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        std::cout << "waiting for thread..." << std::endl;
    }

    return 0;
}

我错过了什么?目前的做法是否正确?如果不是,我该怎么做呢?感谢

2 个答案:

答案 0 :(得分:0)

在您发布的代码中,异常检查仅发生一次,并且可能在线程启动之前发生。

此外,您正在从主机线程中捕获错误,但您所引发的错误是在第二个主题上。

我通过在检查异常之前等待第二个线程完成来解决这些问题。

无论如何,可以在此处找到在线程中抛出异常的范例方法:How can I propagate exceptions between threads?

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

static std::exception_ptr _exceptionPtr = nullptr;

struct WorkerThread
{
    std::thread thread;

    void doSomething()
    {
        int seconds = 0;
        bool shouldStop = false;

        while (shouldStop == false)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            std::cout << "time passed : " << ++seconds << "seconds" << std::endl;

            if (seconds == 10) // something bad happened 10 seconds later
            {
                try
                {
                    shouldStop = true;
                    throw std::runtime_error("something really bad happened");
                }
                catch (const std::runtime_error &ex)
                {
                    _exceptionPtr = std::current_exception();
                }
            }
        }
    }

    void run()
    {
        thread = std::thread([this] { doSomething(); });
        //thread.detach();
    }
};

int main(int argc, char *argv[])
{
    WorkerThread workerThread;

        workerThread.run();
        workerThread.thread.join();
        if (_exceptionPtr)
        {
            try
            {
                std::rethrow_exception(_exceptionPtr);
            }
            catch (std::runtime_error &ex)
            {
                // terminates program if exception happens
                std::cout << "Program will now exit" << std::endl;
                exit(EXIT_FAILURE); // but program never executes till here
            }
        }

    for (;;)
    {
        // do A
        // do B
        // do C
        // do ...
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        std::cout << "waiting for thread..." << std::endl;
    }

    return 0;
}

答案 1 :(得分:0)

异常应该在for循环而不是workerThread.run()中捕获,因为run()将立即退出。

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

static std::exception_ptr _exceptionPtr = nullptr;

struct WorkerThread
{
    std::thread thread;

    void doSomething()
    {
        int seconds = 0;
        bool shouldStop = false;

        while (shouldStop == false)
        {
            std::this_thread::sleep_for(std::chrono::milliseconds(1000));
            std::cout << "time passed : " << ++seconds << "seconds" << std::endl;

            if (seconds == 10) // something bad happened 10 seconds later
            {
                try
                {
                    shouldStop = true;
                    throw std::runtime_error("something really bad happened");
                }
                catch (const std::runtime_error &ex)
                {
                    _exceptionPtr = std::current_exception();
                }
            }
        }
    }

    void run()
    {
        thread = std::thread([this] { doSomething(); });
        thread.detach();
    }
};

int main(int argc, char *argv[])
{
    WorkerThread workerThread;

    workerThread.run();



    for (;;)
    {
        // do A
        // do B
        // do C
        // do ...
        std::this_thread::sleep_for(std::chrono::milliseconds(1000));
        std::cout << "waiting for thread..." << std::endl;

        if (_exceptionPtr)
        {
            try
            {
                std::rethrow_exception(_exceptionPtr);
            }
            catch (std::runtime_error &ex)
            {
                // terminates program if exception happens
                std::cout << "Program will now exit" << std::endl;
                exit(EXIT_FAILURE); // but program never executes till here
            }
        }
    }

    return 0;
}

致@liliscent的信用