关于Qt在新线程中创建定时器的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于Qt在新线程中创建定时器的问题相关的知识,希望对你有一定的参考价值。

想在新创建的线程中定义一个100ms的定时器,一旦timeout就调用槽函数发送网

络数据
但成功启动线程后从未跳入槽函数,为什么鸟?
代码大致如下:

// .h文件
#include<QThread>
#include<QTimer>

class NewThread : public QThread

public:
NewThread();
QTimer *m_timer;

private slots:
void sSend();


// .cpp文件
#include ".h"

NewThread::NewThread()

m_timer = new QTimer(this);


NewThread::run()

m_timer->start(100);
connect(m_timer, SIGNAL(timeout()), this, SLOT(sSend()));

while(1)

Sleep(1);



NewThread::sSend()

...

参考技术A NewThread::sSend()

...

返回类型都没有···

在 QDialog 中创建线程并在 Qt 中向 QDialog 发出信号

【中文标题】在 QDialog 中创建线程并在 Qt 中向 QDialog 发出信号【英文标题】:Create Thread in QDialog and emit signals to QDialog in Qt 【发布时间】:2013-09-03 14:12:27 【问题描述】:

我创建了一个具有主窗口的应用程序,并从该窗口创建了一个 QDialog。这个 QDialog 应该创建一个 RenderThread,它从相机发出接收到的图像,或者在示例中发出文本。当我调试它时,似乎永远不会建立连接,因为在插槽CameraWindow::debugSomething 中添加断点不会被捕获。怎么了 ? 我按照这个例子:http://qt-project.org/doc/qt-4.8/threads-mandelbrot.html,但似乎我做错了什么。

qtDEVC::qtDEVC(QWidget *parent, Qt::WFlags flags)
    : QMainWindow(parent, flags)

    ui.setupUi(this);
    connect (ui.pushButton_startCam, SIGNAL( clicked() ),this,SLOT( startCam() ) );

    /**Threading*/
    CameraWindow camWindow = new CameraWindow(this);



int qtDEVC::startCam()

    camWindow.show();
    camWindow.startCaptureThread();

CameraWindow 类:

 CameraWindow::CameraWindow(QWidget *parent)
        : QDialog(parent)
    
    ui.setupUi(this);

    connect(&thread, SIGNAL(sendText(std::string)),
        this, SLOT(debugSomething(std::string)));


void CameraWindow::debugSomething(std::string something)
    QString somethings(something.c_str());
qDebug()<<somethings;


int CameraWindow::startCaptureThread()

    RenderThread *thread = new RenderThread(this, guid, CLEYE_COLOR_RAW, CLEYE_VGA, 50); 

    thread->StartCapture(); //starts thread in low priority and sets _running to true

CameraWindow 标题

 class CameraWindow : public QDialog
 
    Q_OBJECT

    public:
    CameraWindow(QWidget *parent = 0);
    ~CameraWindow();
    Ui::CameraWindow ui;

public slots:
    int startCaptureThread();
    void debugSomething(QString);

private:
    RenderThread thread;
;

渲染线程类

 void RenderThread::run()
 

    // image capturing loop
    while(_running)
    
    qDebug()<<("render while()"); //is printed with qdebug correctly
    if (restart)
        break;
           if (abort)
               return;

    qDebug("it");  //is also printed with qdebug correctly

    emit sendText(text);

渲染线程头

class RenderThread : public QThread

    Q_OBJECT

public:
    RenderThread(QObject *parent, GUID cameraGUID, CLEyeCameraColorMode mode, CLEyeCameraResolution resolution, float fps);
    RenderThread();
    ~RenderThread();

    bool StartCapture();

signals:

    void sendText(QString &text);

protected: 
    void run();

private:
    QMutex mutex;
    QWaitCondition condition;
    //some more private variables for construction

;

我认为这个创作似乎有些错误:RenderThread *thread = new RenderThread(this);

【问题讨论】:

将连接参数设置为QString,而不是std::string。 将 std::string 注册为元类型。请检查类似的 SO[Using std::string failed Signals and Slots][1] [1]: ***.com/questions/17121554/… 改成QString没有效果 什么是运行时错误? 没有它只是不发射 【参考方案1】:

这个问题首先担心的是“RenderThread”这个词。请注意,Qt 只允许在主线程上渲染。您可以创建单独的线程来计算图像数据,但无论何时使用画家和绘制对象,都必须在主线程上进行。但是,如果您只是要捕获图像并将其通过信号和插槽传递给主线程,那应该没问题。

其次,虽然您没有显示所有代码,但我从名为 RenderThread::run() 的函数和 Qt 示例中假设您可能从此处的 QThread 继承。如果是这种情况,请注意这不是如何使用 QThread。相反,您应该让您的类继承自 QObject 并将其移至 QThread。你可以阅读如何use QThread properly here。

我知道这是您遵循的 Qt 示例,但即使是 Qt 的人也认为这是一个坏主意。 Here's an article 如何真正使用 QThreads。

考虑到这一点,以下是我将如何使用 QThread 的概要:-

class CameraWindow : public QDialog

    private:
      CameraObject* m_pCamObject;
;

class CameraObject : public QObject

    Q_OBJECT
    public:

    private slots:
         startCaptureThread();

    private:
;

int CameraWindow::startCaptureThread()

     m_pCamObject = new CameraObject;

     QThread* pThread = new QThread;

     this->moveToThread(pThread); // CameraObject will run on the new thread

     connect(pThread, SIGNAL(started()), m_pCamObject, SLOT(startCaptureThread()));
     connect(pThread, SIGNAL(finished()), pThread, SLOT(deleteLater()); // clear up when 

完成

     pThread->start();

注意这里是一个CameraObject,与CameraWindow分开。 QThread 只是线程的一个控制器,它与 CameraObject 保持清晰的分离。

以这种方式处理线程的另一个原因是您可以将多个 QObject 实例移动到新线程,而不是总是为每个对象创建一个新线程。如果线程数多于 CPU 内核数,则不太可能通过创建另一个线程来获得收益。

【讨论】:

thread-&gt;StartCapture(); //以低优先级启动线程并将_running设置为true。我已经读到使用线程存在混淆,但事实是我不能发出这个信号并且需要让它工作。我是 qt 的初学者并且愿意学习,但目前我需要让它工作;)命名类“RenderThread”是基于示例并在我确定我不必花费我的建立与 QT 提供的基础架构不同的基础架构的时间 我想我明白你的意思了,非常感谢你的建议。在从 1 到 10 的范围内,你有多确定它会起作用,因为这是我第三次尝试使用提供的 qt 基础设施来让它工作,这给 qt 中的线程一个非常差的等级我猜......为什么它不像在提供示例? 如果您根据使用 QThreads 正确编码而不从它们继承,那么它将工作,假设您已经建立了正确的连接。正如我所说,Qt 的开发人员声称各种示例通过继承使用 QThreads,但它被滥用了。 QThread 是一个线程管理类,所以只有在需要重写底层线程机制的处理时才应该被继承。 所以我猜这个问题没有 1line 解决方案,我需要掉头,这很糟糕,因为这些只是我迄今为止编写的所有代码的简短片段.. 是的,它不是 1 行,但也不是很多。如果你有一个基于 QObject 的项目要放在另一个线程上,那么实际上只有 3 行可以让它工作。创建线程,将对象移动到线程,调用thread->start()。其他一切都在处理连接以及您希望 QObject 做什么。【参考方案2】:

在CameraWindow 类的构造函数中,您连接的是RenderThread 的信号,但它不是在startCaptureThread 中启动的同一个对象。像这样更改您的 startCaptureThread:

int CameraWindow::startCaptureThread()

    thread.StartCapture(); //starts thread in low priority and sets _running to true

在这个方法中,CameraWindow的线程成员被启动。

P.S.:也贴出标题,我们无法从这段代码中看到成员。

【讨论】:

我得到error C2228 这样做。我会发布标题【参考方案3】:

在上述示例中,CameraWindow 类包含一个 RenderThread thread 变量,而不是 RenderThread *thread

您正在连接调用中的指针地址:

connect(&thread, SIGNAL(sendText(std::string)),
    this, SLOT(debugSomething(std::string)));

尽量使用好的地址:

connect(thread, SIGNAL(sendText(std::string)),
    this, SLOT(debugSomething(std::string)));

这不是经过测试的答案。

【讨论】:

connect 调用将指针作为参数,因此他的 connect 调用没有任何问题。

以上是关于关于Qt在新线程中创建定时器的问题的主要内容,如果未能解决你的问题,请参考以下文章

Qt中定时器问题

在 Windows 中创建 C++ 非阻塞计时器

定时扫描串口看设备是不是连接在QT、QSerialPort

在新窗口 C++ 中创建线程

QT用线程启动定时器

Qt——线程与定时器