1

问题

我目前正在将 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 */

看起来很有趣,我只需要一个类似于处理请求的 QNetworkReply 的 QObject 派生类。

当我使用该代码时,我遇到的问题是我的 QNetworkReply 实现不会等待 loop.exec() 运行,然后循环不会接收到 finished() 信号。

但是没有比生成 QEventLoop 更简单的事情了吗?

注意:[1] 的示例中的 QNetworkReply 和 QNetworkAccessManager 是在 pthread 中生成的,但是我需要能够使用 SIGNALS 和 SLOTS 与 QCoreApplication 的偶数队列进行通信,因为其中包含数据的对象来自不同的 QThread (在这要么是 QCoreApplication 要么是一个特殊的 QThread)。

使用 Qt::QueuedConnection

我还发现了 [2],也许:

连接(src,SIGNAL(信号签名),dest,SLOT(插槽签名),Qt::QueuedConnection);

这就是我想要的,但我对此表示怀疑。

链接

4

2 回答 2

0

是的,你想要 Qt::QueuedConnection 方法。但还要确保您使用的是多线程 Qt 库。IIRC 它是一个构建时选项。

另请参阅:Qt 文档

于 2013-10-17T12:49:13.887 回答
0

您可能面临的是QNetworkAccessManager 内部使用线程来处理 http 请求。这就是为什么它“不等待”你。修复它需要一个相当简单的修改:

QNetworkAccessManager qnam;
QEventLoop loop;
QNetworkReply *reply = qnam.get(QNetworkRequest(QUrl(...)));
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
if (!reply->isFinished()) loop.exec();

在多线程中使用 QObjects 的注意事项

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

真正的问题是:每个QObject都有一个线程亲和性。默认关联是实例化对象的线程。您不应该直接从其他线程使用此类对象。

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

每当你这样做emit object->signal(...)时,以下不变量应该成立:

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

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

如果断言失败,您需要使用QObject::moveToThread将对象移动到要触发其信号的线程。您可以QThread通过pthread调用QThread::currentThread()pthread. QThread将自动为您创建一个实例:)

于 2013-10-17T14:06:49.933 回答