Qt:Worker线程和GUI事件之间的关系

时间:2017-07-14 08:37:03

标签: c++ qt

我有一个普通的GUI线程(主窗口),并希望将一个Worker线程附加到它。 Worker线程将被实例化,移动到它自己的线程然后被激发掉以独立运行,运行消息传递例程(非阻塞)。

这是创建工作人员的地方:

void MainWindow::on_connectButton_clicked()
{
    Worker* workwork;
    workwork= new Worker();

    connect(workwork,SIGNAL(invokeTestResultsUpdate(int,quint8)),
                      this,SLOT(updateTestResults(int,quint8)),Qt::QueuedConnection);
    connect(this,SIGNAL(emitInit()),workwork,SLOT(init()));

    workwork->startBC();
}

这是工人开始的地方:

void Worker::startBC()
{
    t1553 = new QThread();    
    this->moveToThread(t1553);
    connect(t1553,SIGNAL(started()),this,SLOT(run1553Process()));
    t1553->start();
}

这里有两个问题,关于新线程的事件队列:

第一个也是小问题是,虽然我可以从Worker线程接收信号(即:invokeTestResultsUpdate),但我不能通过发出init信号来调用emitInit方法来自MainWindow。除非我直接调用它或通过Qt::DirectConnection连接它,否则它不会触发。为什么会这样?因为我必须明确地启动Worker线程自己的消息循环?或者其他一些我不知道的事情? (即使我尝试,我也无法绕过线程/事件循环/信号槽机制的概念以及彼此之间的关系。我也欢迎任何新观点。)

第二个也是更加模糊的问题是:run1553process方法会执行一些 。繁重的工作,我的意思是非常高的数据率。有一个循环正在运行,我尝试使用大多数extern API函数接收从设备(实时)流入缓冲区后的数据。然后每次收到消息时,将提到的invokeTestResultsUpdate信号抛向GUI,更新消息编号框。它只不过是。

我遇到的事情很奇怪;通常,消息传递例程大多不受阻碍,但是当我调整主窗口大小,移动它,或隐藏/显示窗口时,工作线程会跳过许多消息。调整大小的动作非常缓慢(响应速度非常快)。它确实给了我一个癌症。

(注意:我之前尝试过继承QThread,它没有减轻问题。)

我一直在阅读所有"线程亲和力"主题并试图应用它们,但它仍然表现得像某种程度上由GUI线程的事件以某种方式中断。我可以理解MainWindow的麻烦,因为队列中有许多消息要执行(调用的插槽和GUI事件)。但我无法看到为什么后台线程受GUI事件的影响。我真的需要一个非常强大且不受阻碍的消息程序单独运行,触发并忘记信号,而不是对任何事情一无所知。

我现在非常渴望得到任何帮助,所以任何信息对我都有用。请毫不犹豫地提出想法。

2 个答案:

答案 0 :(得分:1)

TL; DR:QCoreApplication::processEvents();内的periodiacally呼叫run1553process

完整说明: 来自主线程的信号被放入队列中并在第二线程中的事件循环获得控制时执行。在您的实现中,一旦线程启动,您就会调用run1553Process。控件将不会返回到事件循环,直到该函数结束或手动调用QCoreApplication::processEvents,因此信号将位于那里等待事件循环拾取它们。

P.S。 你正在泄漏上面代码中的工人和线程

P.P.S。 来自设备的数据流通常提供异步API,而不是必须以不确定的方式轮询它们

答案 1 :(得分:0)

我终于找到了问题。

关键错误是将QThread的内置start()信号连接到run1553Process()插槽。我曾想过用这种方法取代run(),并期望一切都好。但这导致实际的run()方法被阻止,因此阻止了事件循环的启动。

如qthread.cpp中所述:

void QThread::run()
{
    (void) exec();
}

要解决此问题,我没有触及原始的start()信号,而是将另一个信号独立地连接到我的run1553Process()。首先通常启动线程,允许事件循环开始,然后触发我的其他信号。这样做了,现在我的工作人员可以收到所有消息。

我认为现在我更了解线程和事件之间的关系。

顺便说一下,这个解决方案并没有完全解决消息跳过问题,但我觉得这是由另一个因素引起的(比如我的消息读取实现)。

感谢大家的想法。我希望这个解决方案可以帮助像我这样的其他穷人。

相关问题