- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我在使用 Qt 线程和连接时遇到了一些问题。我找到了几个关于这个主题的教程和讨论,我关注了this tutorial创建线程。但我仍然遇到问题,即在线程上调用 wait() 永远不会返回并且 UI 卡住。
之前在这里问过类似的问题(第二个例子): Qt connection type between threads: why does this work?
在问题的最后一次编辑中,作者提到他造成了僵局。我假设,我在我的应用程序中做同样的事情。但是我还是不明白,为什么会这样。阅读 suggested article没有帮助我理解。我只是明白了,死锁可能会发生,但我不知道是什么原因造成的,或者在我的情况下。
我还创建了一个简化为核心问题的示例。找到此问题底部的代码。
所以我的问题是:在我的示例中,死锁的确切原因是什么?有没有不用直接连接的解决方案?
如果有任何提示,我将不胜感激。
谢谢!
编辑:
由于评论,我尝试通过信号发送停止请求,并在线程循环中添加了 QCoreApplication::processEvents() 调用。但主要问题还是一样。
编辑 2:
在对事件循环进行更多思考后,我找到了一个可接受的解决方案:
thread.requestStop();
// now instead of using wait(), we poll and keep the event loop alive
// polling is not nice, but if it does not take a very long time
// for the thread to finish, it is acceptable for me.
while (thread.isRunning())
{
// This ensures that the finished() signal
// will be processed by the thread object
QCoreApplication::processEvents();
}
这确实有效,工作人员自己控制如何停止工作。
想到这个之后,对于卡顿的问题我也有了一个解释:调用wait好像是让主线程要么忙要么挂,所以它不处理任何事件。由于线程对象存在于主线程中,因此线程的 finished() 信号被排队但从未被处理。
我隐含的假设,即 thread.wait() 仍会保持事件循环工作,显然是错误的。但是,QThread::wait() 函数有什么用?!?
这只是一个理论,但也许这里有人可以验证或证伪它......
编辑 3(最终解决方案):
看完this small article并实现子类化解决方案,我认为这对于这个特定问题更可取。不需要事件循环,我可以在不同的线程上直接调用并使用互斥锁保护。它的代码更少,更易于理解和调试。
我认为我只会使用非子类化策略,如果与线程的交互不仅仅是启动和暂停的话。
我的简化示例
也许我应该指出,我没有删除线程,因为在我原来的应用程序中,我想稍后恢复,所以停止它实际上意味着暂停它。
worker.h:
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QMutex>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject* parent = NULL);
public slots:
void doWork();
void requestStop();
signals:
void finished();
private:
bool stopRequested;
QMutex mutex;
};
#endif // WORKER_H
worker .cpp:
#include "worker.h"
#include <QThread>
#include <iostream>
using namespace std;
Worker::Worker(QObject *parent)
: stopRequested(false)
{
}
void Worker::doWork()
{
static int cnt = 0;
// local loop control variable
// to make the usage of the mutex easier.
bool stopRequesteLocal = false;
while (!stopRequesteLocal)
{
cout << ++cnt << endl;
QThread::msleep(100);
mutex.lock();
stopRequesteLocal = stopRequested;
mutex.unlock();
}
cout << "Finishing soon..." << endl;
QThread::sleep(2);
emit finished();
}
void Worker::requestStop()
{
mutex.lock();
stopRequested = true;
mutex.unlock();
}
主程序:
#include <QCoreApplication>
#include <QThread>
#include <QtCore>
#include <iostream>
#include "worker.h"
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QThread thread;
Worker worker;
QObject::connect(&thread, SIGNAL(started()), &worker, SLOT(doWork()));
// this does not work:
QObject::connect(&worker, SIGNAL(finished()), &thread, SLOT(quit()));
// this would work:
//QObject::connect(&worker, SIGNAL(finished()), &thread, SLOT(quit()), Qt::DirectConnection);
// relocating the moveToThread call does not change anything.
worker.moveToThread(&thread);
thread.start();
QThread::sleep(2);
worker.requestStop();
cout << "Stop requested, wait for thread." << endl;
thread.wait();
cout << "Thread finished" << endl;
// I do not know if this is correct, but it does not really matter, because
// the program never gets here.
QCoreApplication::exit(0);
}
最佳答案
我将自己的答案作为 EDIT 3 添加到问题文本中。
关于c++ - QThread::wait() 不使用直接连接不返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20640068/
我想写一些必须在自己的线程中工作的类。我读过这篇文章:http://wiki.qt.io/Threads_Events_QObjects。它建议移动必须在自己的线程中工作的对象,例如: TestCla
在调用所有与 QThread::finished() 信号关联的槽后,QThread::wait() 是否返回(即解除阻塞执行)? 提前致谢。 最佳答案 不,它可能会在与信号 finished() 关
我不是在打电话 exec()在我的代码中,但 timer和 QUdpSocket工作正常。是 exec()用于等待 event接着说? 更新:timer正在工作,因为我没有调用 moveToThrea
如果我创建 QThread 作为局部变量,我发现了一个奇怪的行为。 例如,下面的代码将作为单线程工作,这意味着我需要等待 10 秒,结果才会出来。 但是如果我将线程从局部变量更改为成员变量,它将作为多
I solved my issue by moving the mySubQThread run() into the myQThread run() That said, I still would
一段时间以来,我一直在使用 Qt 开发一个应用程序,在该应用程序中我必须从相机中抓取帧。相机将在与应用程序其余部分不同的线程中运行。我遵循了以下建议: http://mayaposch.wordpre
考虑以下代码片段: class ThreadA::QThread { public: ThreadA() { } void run() { myVariable = n
所以我在构造函数中有以下代码。 m_someObject = new SomeObject(); m_someObject->moveToThread(&m_thread); m_thread.sta
我有 3 个 QThreads 相互调用(全部继承自 QThread。我知道有些人可能建议使用 moveToThread,但暂时忽略这个事实)。简化的代码如下所示: Thread1 类: void T
我想知道 new QThread(this) 和 new QThread() 之间有什么区别,以及这将如何影响我的代码在使用 QThread 时的行为. 最佳答案 QThread 的父级谁执行什么没有
我是 PySide2 的新手。我只是想启动一个示例应用程序并在应用程序启动时启动一个线程,并希望在应用程序关闭时停止该线程。当我关闭应用程序时,我收到以下错误:QThread:在线程仍在运行时销毁。s
关于如何实例化和使用 QThread 的官方文档可以在这里找到: http://doc.qt.io/qt-5/qthread.html 该文档描述了两种基本方法:(1) 工作对象方法和 (2) QTh
我有以下设置: int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); // Create the DBM
这是 QTread 的子对象...并在主线程中将其具体化.... 运行时错误如下: ASSERT failure in QCoreApplication::sendEvent: "Cannot sen
在过去的几天里,我一直在尝试使用 QThreads 而不对 QThread 进行子类化的新的首选方法。我遇到的麻烦是当我试图关闭我创建的一组线程时。我经常收到“线程仍在运行时已被销毁”消息(如果我在
我已经创建了这个继承自QThread的类,用于向数据库服务器发送数据,你觉得怎么样?可以改进吗? 谢谢 #ifndef QUERYTHREAD_H#define QUERYTHREAD_H#inclu
我需要在一个线程中进行无限循环。 在 this article作者写道 >you should never ever block the event loop 因为它会阻塞信号槽概念。如何在 QTh
我试图在一个单独的线程中执行一些工作,并在工作完成后停止该线程。 我已经建立了这样的连接 thread.connect( workerClass, SIGNAL( finished() ), SLOT
我有一个快速的问题。我应该创建一个小的多线程程序来从多个传感器获取数据,并且我了解 pthreads 和 qthreads。我可以访问两个图书馆。我个人偏向于使用 Qt,因为它的设计和各种功能。但是,
我需要在主线程上运行 QThread::usleep() (出于各种原因)。 但是,usleep 是受静电保护的。 我想在没有包装器的情况下使用 QThread 的 usleep 函数(我目前正在使用
我是一名优秀的程序员,十分优秀!