简体   繁体   English

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

[英]How to properly embed QEventLoop in the std::thread?

There is an object that contains std::thread that I want to be finished when the object is destroyed. 有一个包含std::thread的对象,该对象销毁后我要完成。

Minimal working code: 最少的工作代码:

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

It becomes complex very fast: you can call exit() on the loop only after it enters the exec() , you can't create the loop outside of the thread. 它变得非常复杂:您只能在进入exec()后在loop上调用exit() ,而不能在线程外部创建loop

I only have a solution with a semaphore that is released by a handler that is queued for the execution in this loop. 我只有一个带有信号量的解决方案,该信号量由在此循环中排队等待执行的处理程序释放。 When the semaphore is released I can be sure that the loop is created and running, so it can be terminated with a quit() message when needed. 释放信号量后,我可以确定该循环已创建并正在运行,因此可以在需要时使用quit()消息终止该循环。

Am I missing a simpler way? 我想念一个更简单的方法吗?

Maybe you could pass a reference to a unique_ptr of QEventLoop to the thread and at destruction call exit on that pointer. 也许您可以将对QEventLoop的unique_ptr的引用传递给线程,并在该指针的销毁调用出口处传递该引用。 Like this: 像这样:

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

Here's my take on it, based on katrasnikj's answer and std::promise docs to ensure that the thread is running by the time the constructor finishes. 这是我的看法,基于katrasnikj的答案和std :: promise文档,以确保在构造函数完成时线程正在运行。

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

But you might want to look into using QThread instead, since it's capable of running its own event loop. 但是您可能想研究使用QThread ,因为它能够运行自己的事件循环。

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

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