如何在std :: thread中正确嵌入QEventLoop?

时间:2017-11-22 10:46:52

标签: c++ multithreading qt concurrency

有一个对象包含std::thread,我希望在对象被销毁时完成。

最小工作代码:

#include <thread>
#include <future>
#include <QEventLoop>

struct Connector
{
    Connector(std::string addr, std::function<void(std::string)> cb)
    {
        std::promise<void> barrier;
        auto fut = barrier.get_future();

        m_worker = std::thread([addr, cb, &barrier]()
        {
            QEventLoop loop;
            QTimer::singleShot(0, [this, &barrier, &loop]
            {
                m_quit = [&loop] { QTimer::singleShot(0, &loop, &QEventLoop::quit); };
                barrier.set_value();
            });

            MySocket s(addr, cb);

            loop.exec();
        });

        fut.wait();
    }

    ~Connector()
    {
        m_quit();
        m_worker.join();
    }

    std::thread worker;
    std::function<void()> m_quit;
};

它变得非常复杂:只有在exit()进入loop后,您才能在exec()上致电loop,您无法在quit()之外创建for线程。

我只有一个信号量的解决方案,该信号量由在此循环中排队等待执行的处理程序释放。释放信号量时,我可以确定循环已创建并正在运行,因此可以在需要时使用$ids = explode(',', $userQrLt['ID']); $names = explode(',', $userQrLt['Name']); foreach($i=0;$i<count($ids);$i++) { echo "http://thewebsite.com/cgi-bin/zd_view.cgi?q=".$ids[$i]."&name=$names[$i]<br />"; } 消息终止。

我错过了一种更简单的方法吗?

2 个答案:

答案 0 :(得分:0)

也许你可以将对一个QEventLoop的unique_ptr的引用传递给该线程,并在该指针的destroy调用exit上传递。像这样:

#include <thread>
#include <QEventLoop>

struct Connector
{
    Connector()
    {
        m_worker = std::thread([=]()
        {
            event_loop = std::make_unique<QEventLoop>();
            loop->exec();
        });
    }

    ~Connector()
    {
        event_loop->exit();
        m_worker.join();
    }

    std::unique_ptr<QEventLoop> event_loop;
    std::thread worker;
};

答案 1 :(得分:0)

根据katrasnikj的回答和std::promise docs,根据katrasnikj的回答和{{3}}来确定线程在构造函数完成时运行。

struct Connector
{
    Connector()
    {
        std::promise<void> barrier;
        auto fut = barrier.get_future();
        worker = std::thread([=](std::promise<void>&& barrier)
        {
            event_loop = std::make_unique<QEventLoop>();
            barrier.set_value();
            event_loop->exec();
        }, std::move(barrier));
        fut.wait();
    }

    ~Connector()
    {
        QTimer::singleShot(0, event_loop.get(), &QEventLoop::quit);
        worker.join();
    }

    std::unique_ptr<QEventLoop> event_loop;
    std::thread worker;
};

但您可能希望使用QThread来代替,因为它能够运行自己的事件循环。