繁体   English   中英

Qt在另一个线程中为工作者对象排队退出事件

[英]Qt queued exit event for worker object in another thread

MyClass对象有一个工作器QObject ,它正在另一个线程中工作:

class MyClass {
....
private:
   QThread thread;
   Worker worker; // inherits QObject
};

...

worker.moveToThread(&thread);

现在,当我调用thread.exit()我的工作线程会立即停止。 我希望它完成所有待处理的事件,然后退出。

我已经尝试过类似“排队退出”的方法:

connect(this, SIGNAL(signalFinish()),
        &thread, SLOT(quit()),Qt::QueuedConnection);

 ...

void MyClass::finish()
{
    emit signalFinish();
    worker.disconnect(); // do not queue any more events
    thread.wait();
}

但这不起作用。 它将永远等待...

在事件循环将处理所有未决事件之后,如何停止QThread

线程和MyClass实例都位于同一线程中-可能是主线程:

MyClass::MyClass() {
  ...
  Q_ASSERT(this->thread() == thread.thread());

但是,您要排队到worker对象的事件将进入worker线程:

  worker.moveToThread(&thread);
  Q_ASSERT(worker.thread() == &thread);
  Q_ASSERT(worker.thread() != thread.thread());

排队的连接恰恰是错误的事情,因为一旦您等待辅助线程,主线程的事件循环就不会运行,也不会再向该线程发出任何事件。 quit调用永远不会传递,因为它是在主线程中传递的,但是主线程被阻塞了。

而是利用quit成为线程安全方法的优势。 从工作线程本身调用它:

//                                    vvvvvvv thread context object for the call
connect(this, &MyClass::signalFinish, &worker, [this]{ thread.quit(); });
// the `quit()` will execute in `worker.thread()`

需要注意的是线程上下文对象是一个对象,其thread()调用将被执行。这应该是一个QThread情况下,在大多数情况下!

signalFinish被发射,一个QMetaCallEvent携带上述算符将在工作线程的队列中排队,并且在任何现有的呼叫(和其他)事件被首先处理将得到执行。

由于您要在主线程中调用finish ,因此您可能不想在该线程上等待,因为这会阻塞GUI,并使您的应用程序无响应。

看来您正在将工作项提交给工作线程, QtConcurrent::run可能会更好地为您提供服务,该程序将工作项提交给线程池,并为您执行所有线程管理。 有关完整示例,请参见此答案 请参阅此答案以及该答案的一些相关花絮。

请参阅此相关的StackOverflow答案。

您可以使用QThread :: exec()调用在事件循环中运行线程。 线程将运行它,直到您通过调用QThread :: exit()告诉线程退出。 因此,一些示例代码如下所示:

void DownloadWorker::run()
 {
    DownloadManager* pDownloadManager = new DownloadManager(this);
    connect(pDownloadManager, SIGNAL(finished()), SLOT(exit()));
    connect(pDownloadManager, SIGNAL(error()), SLOT(exit()));
    pDownloadManager->download();
    exec();
 }

这将确保您在发出DownloadManager的“ finished()”信号之前不会退出线程。

注意:这里我举了一个示例来说明如何解决您的问题,但我不知道您的整个应用程序代码。 这意味着不能保证此代码是线程安全的和一致的。 您需要自己照顾互斥锁和所有正确的同步。 要非常小心 ! 使用这样的“低级”线程API可以使您更好地理解multithereading。

暂无
暂无

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

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