我目前正在将FUSE与qt5放在一起。 Qt和FUSE之间没有桥梁,FUSE主线程(产生其他工作的FUSE线程)和QCoreApplication都只是并排运行。
但我希望能够使用Qt的SIGNALS和SLOTS在基于QObject的对象和[0]中显示的pthread的Read(..)函数之间发送和接收数据。
现在我想改变[0]中的Read(..)函数,使用Qt的SIGNALS和SLOTS从基于QObject的类中检索数据。从pthread发送信号有效但没有明确的QEventLoop我无法收到回复。因此,我正在查看[1]中的代码,该代码设计非常出色,但我还没有使用它。
伪代码(取自[1]):
QNetworkAccessManager qnam;
QNetworkReply *reply = qnam.get(QNetworkRequest(QUrl(...)));
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
/* reply has finished, use it */
看起来很有趣,我需要的是一个QObject派生类,类似于处理请求的QNetworkReply。
当我正在使用该代码时,我遇到的问题是我的QNetworkReply实现不会等待loop.exec()运行,然后循环不会收到finished()SIGNAL。
但是没有比生成QEventLoop更容易的东西吗?
注意:来自[1]的示例中的QNetworkReply和QNetworkAccessManager是在pthread内部生成的,但是,我需要能够使用SIGNALS和SLOTS与QCoreApplication的偶数队列进行通信,因为具有数据的对象它来自不同的QThread(在QCoreApplication或特殊的QThread中)。
我也发现[2]并且可能:
connect(src,SIGNAL(signal-signature),dest,SLOT(slot-signature),Qt :: QueuedConnection);
是我想要的,但我怀疑。
答案 0 :(得分:0)
是的,您需要Qt :: QueuedConnection方法。但也要确保您使用的是多线程Qt库。 IIRC是一个构建时选项。
另请参阅:Qt documentation
答案 1 :(得分:0)
您可能面临的是QNetworkAccessManager
internally uses threads to process http requests。这就是为什么它“不等待”你。修复它需要一个相当简单的修改:
QNetworkAccessManager qnam;
QEventLoop loop;
QNetworkReply *reply = qnam.get(QNetworkRequest(QUrl(...)));
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
if (!reply->isFinished()) loop.exec();
当作为信号源的对象存在(被实例化)与具有槽的对象的线程不同的线程时,该连接将自动为QueuedConnection
类型。
真正的问题是:每个QObject
都有线程关联。默认亲缘关系是实例化对象的线程。你不应该直接从其他线程使用这些对象。
您可能正在做的是在同一个线程中实例化发送方和接收方对象,然后从另一个线程发出信号。这是潜在错误错误的来源,如果此类对象的用户强制进行非自动直接连接,则会导致未定义的行为。
无论何时执行emit object->signal(...)
,都应保留以下不变量:
Q_ASSERT(QThread::currentThread() == object->thread());
随意在您明确执行的每个emit()
前面添加这些不变检查。
如果断言失败,则需要使用QObject::moveToThread
将对象移动到要触发其信号的线程。通过从QThread
中运行的代码调用pthread
,您可以获得给定QThread::currentThread()
的{{1}}。将为您自动创建pthread
的实例:)