Qthread 调用只运行一次

Posted

技术标签:

【中文标题】Qthread 调用只运行一次【英文标题】:Qthread calls run only once 【发布时间】:2015-05-22 13:44:31 【问题描述】:

您好,我正在尝试在 Qt 的控制台应用程序中创建线程。

我的主要方法是:

#include<featurematcher.h>
#include<QCoreApplication>

    int main(int argc, char *argv[])
    
        QCoreApplication a(argc, argv);

        FeatureMatcher * fm = new FeatureMatcher();

        fm->start();

    return a.exec();


我的 FeatureMatches 类如下:

    #ifndef FEATUREMATCHER_H
#define FEATUREMATCHER_H
#include<QThread>

class FeatureMatcher:public QThread

    Q_OBJECT
public:
    FeatureMatcher();
    void run();
;

#endif // FEATUREMATCHER_H

和cpp文件:

#include "featurematcher.h"
#include <iostream>
FeatureMatcher::FeatureMatcher()




void FeatureMatcher::run()

    std::cout<<"Process"<<std::endl;

我的问题是,当我开始运行程序时,它只调用一次运行方法。我期望输出是无限数量的“进程”打印出来,但它只打印一次。 我在哪里失踪?

【问题讨论】:

你想用QThread解决什么问题?如果你希望 run 被重复调用,你可能根本不需要线程,而是一个 QTimer。 一个线程只能运行一次run。如果你想多次执行一个任务,你需要一个循环。 @Alexander 谢谢。我在 GUI 上使用线程。在那,它自己调用运行,但后来我知道这是因为 GUI 正在重新绘制自己并一次又一次地调用线程。 【参考方案1】:

首先一般是not a good idea to inherit QThread。但是,如果您绝对必须这样做,则必须自己实现循环。您可以通过两种方式做到这一点。

你可以创建一个QTimer,然后运行QThread::exec

void FeatureMatcher::run()

    this->moveToThread(this);

    QTimer *timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), SLOT(onTimer()));
    timer->setInterval(1000);
    timer->start();
    exec();

或者你可以创建一个无限循环:

void FeatureMatcher::run()

    while (1) 
        std::cout<<"Process"<<std::endl;
    

更新了第一个示例 #2。

【讨论】:

您的第一个示例不正确。 onTimer 插槽不会在 FeatureMatcher 线程上下文中执行。 @hank:谢谢,好久没用了。更新示例。 我正要尝试在运行中使用while循环。但是我在不需要使用任何循环的 gui 应用程序中使用了线程。一旦我启动了线程,它的 run 函数每次都会自行调用。控制台和 gui 应用程序上的线程有什么不同吗? @Amartel:这也是不正确的。计时器已经在FeatureMatcher 线程上下文中创建,因此不需要timer-&gt;moveToThread(this)。这里的问题是FeatureMatcher 对象本身是在主线程中创建的,它的onTimer 也将在主线程上下文中执行。要“修复”这个问题,您应该在 FeatureMatcher 构造函数中使用 hack:this-&gt;moveToThread(this),但这被认为是一种非常糟糕的做法。 @Muhammet Ali Asan:没有区别。 Once I started the thread its run function is called every time by itself - 这听起来很奇怪。 @hank:再次感谢。已编辑。【参考方案2】:

虽然我同意 Amartel 上面所说的(“继承 QThread 不是一个好主意”)。它仍然是一种选择。

如果你仍然想继承 QThread(你真的,可能不需要)试试这个:

    #ifndef FEATUREMATCHER_H
#define FEATUREMATCHER_H
#include<QThread>

class FeatureMatcher:public QThread

    Q_OBJECT
public:
    FeatureMatcher();
    void loopRun();
private:
    void run();
;

#endif // FEATUREMATCHER_H

然后将 looprun() 函数添加到您的 .cpp 文件中:

#include "featurematcher.h"
#include <iostream>
FeatureMatcher::FeatureMatcher()



void FeatureMatcher::run()

    std::cout<<"Process"<<std::endl;


void FeatureMatcher::looprun()

    while(1)
        start();
    

希望我能帮到你。在极少数情况下继承 QThread 是有益的。

这是与/帮助开发 QThread 模块的人之一的博客文章,其中解释了一些困惑:https://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

但是,这篇文章提出了一些反对始终使用工作线程而不是继承 QThreads 的论点:http://woboq.com/blog/qthread-you-were-not-doing-so-wrong.html

【讨论】:

run 是受保护的虚拟程序,当您执行 QThread::start() 时会调用它。你不应该直接调用 run 。你的实现根本不是一个线程。 修复了这个问题。感谢您指出科雷亚!自从我做这种 QThread 实现以来已经有一段时间了。

以上是关于Qthread 调用只运行一次的主要内容,如果未能解决你的问题,请参考以下文章

QThread多线程编程经典案例分析(三种方法,解释了为什么使用moveToThread的根本原因,即为了避免调用QThread::exec() )

调用 quit() 后清理 QThread

从在 QThread 中运行的 C 代码显示 QMessageBox

了解 qthread 子类的运行方法和线程上下文

在qthread中停止长时间运行的进程

QThread 中的 Qt 信号和槽