Sil*_*cer 6 c++ qt qthread qtestlib qsignalspy
我写了一个执行工作对象的线程。一切正常。结果信号也按应有的方式发出。当然,我处理了有关线程/对象关联性的常见错误。
今天我为这些工作线程/线程编写了一个自动化模块测试。我创建了一个 QSignalSpy 来等待工作对象(已移动到线程)发出的信号,如下所示:
QSignalSpy spy(worker, SIGNAL(Success()));
thread.ExecuteWorker();
QVERIFY(spy.wait()); // Error in this line
Run Code Online (Sandbox Code Playgroud)
我在标记行中收到一个众所周知的错误:
QObject::killTimer: timers cannot be stopped from another thread
Run Code Online (Sandbox Code Playgroud)
首先,我预计会出现错误,因为 wait() 中的某些代码在错误的线程中执行。然后我在QSignalSpy的实现中发现了如下代码:
if (!QMetaObject::connect(obj, sigIndex, this, memberOffset, Qt::DirectConnection, 0))
{
qWarning("QSignalSpy: QMetaObject::connect returned false. Unable to connect.");
return;
}
Run Code Online (Sandbox Code Playgroud)
这显然意味着 QSignalSpy 一直使用 DirectConnection 并且不能用于监视生活在不同线程中的对象的信号。
为什么他们在 Qt5.3 中这样编程?这是一个错误还是有意的行为?我该如何解决这个限制?
不幸的是,这是一个长期存在的问题,公平地说是六年多:
几年前,我在 Qt 贡献者峰会上遇到了 Jason,但在那之后,随着诺基亚关闭了他工作的布里斯班办事处,他就离开了诺基亚。之后,遗憾的是,在 Qt 的这个测试模块中没有太多的贡献。
最近在邮件列表上也有更多关于它的讨论:
为什么 QSignalSpy 使用 Qt::DirectConnection?
Roland 提出的解决方案是这样的,维护者 Thiago 也接受了:
if (thread() != QThread::currentThread())
{
QMetaObject::invokeMethod(this, "exitLoop", Qt::QueuedConnection);
return;
}
Run Code Online (Sandbox Code Playgroud)
在 5.4 之前没有这样做真的有点遗憾。话虽如此,随着更改的合并,这将在 Qt 5.4 中得到修复:
使 QTestEventLoop::exitLoop() 线程安全
| 归档时间: |
|
| 查看次数: |
1893 次 |
| 最近记录: |