Qt4:while循环在单独的线程块GUI [英] Qt4: while loop in seperate thread blocks GUI

查看:136
本文介绍了Qt4:while循环在单独的线程块GUI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我有一个简单的Qt4应用程序与开始按钮,停止按钮和文本字段。当按下开始按钮时,产生一个新的线程,该线程不断地递增计数器(在while循环中),并且文本字段被更新以通过信号/时隙反映这个。当按下停止按钮时,计数停止,直到再次按下开始按钮。

So I have a simple Qt4 application with a Start button, a Stop button, and a text field. When the Start button is pressed, a new thread is spawned that continually increments a counter (in a while loop), and the text field is updated to reflect this via signals/slots. When the Stop button is pressed, the counting stops, until the Start button is pressed again.

它工作...排序。它只每秒更新一次计数器;我想要更快,说每秒44100次。然而,取出sleep(1)调用会导致while循环阻塞,不会识别GUI事件,并且应用程序冻结。此外,停止按钮只能工作在第二次尝试?

It works ... sort of. It only updates the counter once per second; I want it to go faster, say 44100 times per second. Taking out the sleep(1) call, however, causes the while loop to block, no GUI events are recognized, and the application freezes. Also, the Stop button only works on the second try?

当我被QThread子类化时,这工作非常好,但我被告知不这样做,我试图做一个解决方案与子类化QObject然后将对象移动到一个QThread ...但它不能像以前一样工作。

This used to work pretty much fine when I was subclassing QThread, but I was told not to do that, so I tried making a solution with subclassing QObject and then moving the object to a QThread ... but it isn't working as well as it used to.

这里的代码:

Worker.h

class Worker : public QObject
{
  Q_OBJECT

  public:
    Worker();

  public slots:
    void process();
    void stopRunning();

  signals:
    void signalValueUpdated(QString);

  private:
    bool running;
};

Worker.cpp

#include "Worker.h"

void Worker::process()
{
    qDebug("Worker thread id %d",(int)QThread::currentThreadId());

    static int value=0;
    running = 1;
    while(running == 1)
    {
        QString string = QString("value: %1").arg(value++);
        sleep(1); //I want to take this out or make it way shorter but I can't without it crashing.

        emit signalValueUpdated(string);

        QCoreApplication::processEvents();       
    }
}

void Worker::stopRunning()
{
    qDebug("stopRunning() invoked");
    running = 0;
}

MainWindow.h

class MainWindow : public QWidget
{
  Q_OBJECT

  public:
    MainWindow(QWidget *parent = 0);

  private:
    //Widgets
    QHBoxLayout * boxLayout;
    QPushButton * startButton;
    QPushButton * stopButton;
    QLineEdit * lineEdit;

    //Thread where the worker lives
    QThread * workerThread;
    //Worker object itself
    Worker * worker;
};

MainWindow.cpp

#include "MainWindow.h"

 MainWindow::MainWindow(QWidget *parent) : QWidget(parent)
{
    boxLayout = new QHBoxLayout(this);
    startButton = new QPushButton("Start Counter", this);
    stopButton = new QPushButton("Stop Counter", this);
    lineEdit = new QLineEdit(this);

    boxLayout->addWidget(startButton);
    boxLayout->addWidget(stopButton); 
    boxLayout->addWidget(lineEdit);

    qDebug("Thread id %d",(int)QThread::currentThreadId());

    workerThread = new QThread;
    worker = new Worker();
    worker->moveToThread(workerThread);

    connect( startButton, SIGNAL(clicked()), workerThread, SLOT(start()), Qt::QueuedConnection ); //When the start button is clicked, start the worker thread
    connect( startButton, SIGNAL(clicked()), worker, SLOT(process()), Qt::QueuedConnection ); //When the start button is clicked, start the worker thread
    connect( workerThread, SIGNAL(started()), worker, SLOT(process()), Qt::QueuedConnection ); //When the worker thread starts, begin the Worker object's process function
    connect( stopButton, SIGNAL(clicked()), worker, SLOT(stopRunning()), Qt::QueuedConnection ); //When the stop button is clicked, invoke the Worker's stopRunning()
    connect( worker, SIGNAL(signalValueUpdated(const QString&)), lineEdit, SLOT(setText(const QString&)), Qt::QueuedConnection ); //When the Worker emits a signalValueChanged, update the lineEdit to reflect this

}

在Worker.cpp中没有sleep(1)和processEvents(),整个事件崩溃了,但是它们被减慢了太多,只是每秒更新一次,而不是1000或更多。如何使while(运行)循环不会阻塞?

Without sleep(1) and processEvents() in Worker.cpp, the whole thing crashes, but with them it is slowed down too much, only updating the number once per second instead of 1000 or more. How can I make the while(running) loop not block?

提前感谢!

推荐答案


  1. 在工作线程中删除 QCoreApplication :: processEvents()如果你不需要它(为什么你需要它?)GUI事件应该已经由主线程处理。 ..)。这可能是您的问题的原因。

  1. Remove QCoreApplication::processEvents() in the worker, if you don't need it (why do you need it? GUI events should be already processed by the main thread...). That may be the cause of your problem.

以正确的方式连接线程信号:

Connect thread signals in the right way:

connect(workerThread, SIGNAL(started()), worker, SLOT(process()));
connect(startButton, SIGNAL(clicked()), thread, SLOT(start()));

(删除 startButton.clicked() - > worker.process() - 它是无用的,不会写在注释中)

(remove the connect of startButton.clicked()->worker.process() - it is useless and does not do what it is written in the comment)

因为将按钮直接连接到worker中的进程是不正确的。你应该将按钮连接到线程的开始,然后线程(开始)到工作 process()。避免直接连接应避免您遇到的GUI冻结问题。

Because connecting the button directly to the process in the worker is not right. You should connect the button to the start of the Thread, then the Thread (with started) to the worker process(). Avoiding direct connections should avoid the GUI freeze problems you are facing.

此外,您需要创建一个新的线程火它每次你点击按钮。您可以通过将按钮连接到窗口中的 SLOT ,然后从中创建线程(在 MainWindow 构造函数不会工作。)

Also, you need to create a new thread and "fire" it every time you click on the button. You may do it by wiring the button to a SLOT in the window, and create the thread from it (creating it in the MainWindow constructor will not work).

从工作程序中获取:

  // You need another slot in MainWindow, let it be "startProcessing()"
  // in MainWindow::MainWindow, connect the start button to startProcessing()
  connect(btnStart, signal(clicked(), this, SLOT(startProcessing())


  // inside the startProcessing slot
  void MainWindow::startProcessing() {
     ...
     Worker* worker = new Worker;
     QThread* thread = new QThread;

     // start the work
     worker->moveToThread(thread);
     connect(thread, SIGNAL(started()), worker, SLOT(process()));

     // Take care of cleaning up when finished too
     connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
     connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
     connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

     thread->start(); 
  }

正如你可能已经注意到的,我添加了代码来清理它 deleteLater())。

As you may have noticed, I added code to clean it up as well (deleteLater()).

停止按钮也会给你一些问题,关于如何继续的想法。

The stop button will also give you some problems, but you should have now a good idea on how to proceed.

这篇关于Qt4:while循环在单独的线程块GUI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆