首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >QSignalSpy不能与线程一起使用

QSignalSpy不能与线程一起使用
EN

Stack Overflow用户
提问于 2014-12-06 20:54:15
回答 2查看 2.2K关注 0票数 6

我编写了一个执行worker对象的线程。一切都很好。此外,产生的信号也会以应有的方式发出。当然,我处理了与线程/对象关联有关的常见错误。

今天,我为这些工作人员/线程编写了一个自动化模块测试。我创建了一个QSignalSpy,以等待由worker对象(移动到线程)发出的信号,如下所示:

代码语言:javascript
复制
QSignalSpy spy(worker, SIGNAL(Success()));
thread.ExecuteWorker();
QVERIFY(spy.wait()); // Error in this line

我在标记行中出现了一个众所周知的错误:

代码语言:javascript
复制
QObject::killTimer: timers cannot be stopped from another thread

首先,我在我这端发现了一个错误,因为wait()中的一些代码在错误的线程中执行。然后,我在QSignalSpy的实现中找到了以下代码:

代码语言:javascript
复制
if (!QMetaObject::connect(obj, sigIndex, this, memberOffset, Qt::DirectConnection, 0))
{
   qWarning("QSignalSpy: QMetaObject::connect returned false. Unable to connect.");
   return;
}

这显然意味着QSignalSpy一直使用DirectConnection,不能用于监视驻留在不同线程中的对象的信号。

他们为什么要在Qt5.3中这样编程呢?这是一个错误,还是故意的行为?我怎样才能绕过这个限制呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-06 21:06:36

不幸的是,这是一个由来已久的问题,应该说是六年多了:

如果从工作线程发出信号,QSignalSpy会崩溃。

几年前,我在Qt贡献者峰会上见过杰森,但在那之后,他离开了诺基亚,因为诺基亚关闭了他工作的布里斯班办公室。在那之后,Qt的这个测试模块并没有做出太多的贡献,可悲的是。

最近在邮件列表上也有更多的关于这个问题的讨论:

为什么QSignalSpy使用Qt::DirectConnection?

罗兰提出的解决方案是,维持者蒂亚戈也接受了以下观点:

代码语言:javascript
复制
if (thread() != QThread::currentThread())
{
    QMetaObject::invokeMethod(this, "exitLoop", Qt::QueuedConnection);
    return;
}

这在5.4之前还没有出现,真是有点丢脸。话虽如此,在合并更改后,QT5.4将对此加以修正:

使QTestEventLoop::exitLoop()线程安全

票数 6
EN

Stack Overflow用户

发布于 2016-01-25 17:03:37

为了使QSignalSpy在线程之间可靠地工作,我使用了以下方法:我将间谍移动到工作线程,并按如下方式重新实现等待函数:

代码语言:javascript
复制
#include <QSignalSpy>
#include <QTime>
struct ThreadsafeQSignalSpy : QSignalSpy
{
    template <typename Func>
    ThreadsafeQSignalSpy(const typename QtPrivate::FunctionPointer<Func>::Object *obj, Func signal0)
        : QSignalSpy(obj, signal0)
    {}

    bool wait(int timeout)
    {
        auto origCount(count());
        QTime timer;
        timer.start();

        while (count() <= origCount && timer.elapsed() < timeout)
            QCoreApplication::instance()->processEvents(QEventLoop::AllEvents, timeout/10);
        return count() > origCount;
    }
};


void TestSuite::testFunction()
{
    QThread thread;
    ...
    ThreadsafeQSignalSpy spy;
    spy.moveToThread(thread);
    /// now wait should work
    ...
    QVERIFY(spy.wait(1000));
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27336400

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档