pthread 2信号和插槽包装器mit QEventLoop

时间:2013-10-17 12:35:21

标签: c++ multithreading qt signals fuse

问题

我目前正在将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中)。

使用Qt :: QueuedConnection

我也发现[2]并且可能:

  

connect(src,SIGNAL(signal-signature),dest,SLOT(slot-signature),Qt :: QueuedConnection);

是我想要的,但我怀疑。

的链接

2 个答案:

答案 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();

在多线程中使用QObject时需要注意的事项

当作为信号源的对象存在(被实例化)与具有槽的对象的线程不同的线程时,该连接将自动为QueuedConnection类型。

真正的问题是:每个QObject都有线程关联。默认亲缘关系是实例化对象的线程。你不应该直接从其他线程使用这些对象。

您可能正在做的是在同一个线程中实例化发送方和接收方对象,然后从另一个线程发出信号。这是潜在错误错误的来源,如果此类对象的用户强制进行非自动直接连接,则会导致未定义的行为。

无论何时执行emit object->signal(...),都应保留以下不变量:

Q_ASSERT(QThread::currentThread() == object->thread());

随意在您明确执行的每个emit()前面添加这些不变检查。

如果断言失败,则需要使用QObject::moveToThread将对象移动到要触发其信号的线程。通过从QThread中运行的代码调用pthread,您可以获得给定QThread::currentThread()的{​​{1}}。将为您自动创建pthread的实例:)