简体   繁体   English

如何在QT GUI应用程序中执行适当的线程处理?

[英]How to do proper threading in QT GUI application?

I want to run two threads concurrently. 我想同时运行两个线程。 I successfully did the same when I ran a program as a QT console application. 当我将程序作为QT控制台应用程序运行时,我成功地做了同样的事情。 Here's the working code of QT console application for multi threading:- 这是用于多线程的QT控制台应用程序的工作代码:

myobject.h myobject.h

#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <QObject>
#include <QDebug>
#include <QThread>

class MyObject : public QObject
{
    Q_OBJECT
public:
    explicit MyObject(QObject *parent = 0);
    void doSetup(QThread &cThread);
    void doSetup2(QThread &cThread2);
signals:

public slots:
    void doWork();
    void doWork2();
};

#endif // MYOBJECT_H

main.cpp: main.cpp:

#include <QtCore/QCoreApplication>
#include <QThread>
#include <myobject.h>
int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QThread cThread, cThread2;
    MyObject cObject, cObject2;

    cObject.doSetup(cThread);
    cObject.moveToThread(&cThread);
    cObject2.doSetup2(cThread2);
    cObject2.moveToThread(&cThread2);
    cThread.start();
    cThread2.start();
    qDebug()<<"hello there ";
    return a.exec();
}

my object.cpp 我的object.cpp

#include "myobject.h"
#include <QThread>
#include "tftpServer.h"

MyObject::MyObject(QObject *parent) :
    QObject(parent)
{
}

void MyObject::doSetup(QThread &cThread)
{
    connect(&cThread, SIGNAL(started()), this, SLOT(doWork()));
}

void MyObject::doSetup2(QThread &cThread2)
{
    connect(&cThread2, SIGNAL(started()), this, SLOT(doWork2()));
}
void MyObject::doWork()
{
    for(int i=0; i<1000; i++)
    {
        qDebug()<<"******************Thread 1";


    }

}
void MyObject::doWork2()
{
    for(int i=1000; i<2000; i++)
    {
        qDebug()<<"Thread 2************************";


    }

}

Here's the output: 这是输出:

******************Thread 1
Thread 2************************
******************Thread 1
Thread 2************************
******************Thread 1
Thread 2************************
******************Thread 1
Thread 2************************

..and so on ..等等

Now when I use this almost same code and run as a QT GUI application, the threads do not run concurrently, but run one after the other. 现在,当我使用几乎相同的代码并作为QT GUI应用程序运行时,线程不会并发运行,而是一个接一个地运行。 Here's the code: 这是代码:

mainwindow.h 主窗口

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDebug>
#include <QThread>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void doSetup(QThread &cThread);
    void doSetup2(QThread &cThread2);
private:
    Ui::MainWindow *ui;

public slots:
    void doWork();
    void doWork2();
};

#endif // MAINWINDOW_H

main.cpp main.cpp

#include <QtGui/QApplication>
#include "mainwindow.h"
#include <QThread>
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    QThread cThread, cThread2;
    MainWindow cObject, cObject2;

    cObject.doSetup(cThread);
    cObject.moveToThread(&cThread);
    cObject2.doSetup2(cThread2);
    cObject2.moveToThread(&cThread2);
    cThread.start();
    cThread2.start();

    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.cpp 主窗口

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
#include <qthread.h>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    qDebug()<<"gui running";
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::doSetup(QThread &cThread)
{
    connect(&cThread, SIGNAL(started()), this, SLOT(doWork()));
}

void MainWindow::doSetup2(QThread &cThread2)
{
    connect(&cThread2, SIGNAL(started()), this, SLOT(doWork2()));
}
void MainWindow::doWork()
{
    //QThread::sleep(100);
    for(int i=0; i<1000; i++)
    {
      qDebug()<<"******************Thread 1";
//      qDebug()<<i;

    }

}
void MainWindow::doWork2()
{
    for(int i=1000; i<2000; i++)
    {
      qDebug()<<"Thread 2************************";
//        qDebug()<<i;

    }

}

Here's the output: 这是输出:

gui running 
gui running 
QObject::moveToThread: Widgets cannot be moved to a new thread
QObject::moveToThread: Widgets cannot be moved to a new thread
gui running 
******************Thread 1 
******************Thread 1 
******************Thread 1 
******************Thread 1

(and so on...) (等等...)

******************Thread 1
Thread 2************************ 
Thread 2************************ 
Thread 2************************ 
Thread 2************************ 
Thread 2************************ 
Thread 2************************ 

(and so on...) Note that the only difference b/w console and gui application I made is changed the base class QObject to QMainWindow, and hence the thread objects so created are objects of QObject & QMainWindow respectively, for console and GUI applications. (依此类推...)请注意,我制作的黑白控制台和gui应用程序的唯一区别是将基类QObject更改为QMainWindow,因此,这样创建的线程对象分别是控制台和GUI的QObject和QMainWindow对象应用程序。

Hoping I am sufficiently clear, can you please tell me what mistake am I committing, which is making the threads run one after the other and not concurrently, as it does for the console application? 希望我足够清楚,您能告诉我我犯了什么错误,这使线程一个接一个地运行,而不是像控制台应用程序那样并发运行?

Thank you. 谢谢。

Any class inherited from QWidget cannot reside in thread other than the main GUI thread. 从QWidget继承的任何类都不能驻留在主GUI线程以外的线程中。 Actually this is what the output said. 实际上,这就是输出所说的。 Your solution is a bad design. 您的解决方案是错误的设计。 Separate the work objects (inherited from QObject, residing in another thread) and the visual objects (inherited from QWidget, residing in the GUI thread), to follow the "one class one responsibility" principle. 将工作对象(从QObject继承,驻留在另一个线程中)和可视对象(从QWidget继承,驻留在GUI线程中)分开,以遵循“一类一负责”的原则。

Another catch in multithreading in Qt is the fact that any QObject cannot reside in different thread than its parent. Qt中多线程的另一个问题是,任何QObject都不能与其父代驻留在不同的线程中。 This is natural because the parent is the owner of the child object, most importantly it takes care of its destruction. 这是很自然的,因为父级是子级对象的所有者,最重要的是,它负责其子对象的销毁。 To enable this, the child cannot be in other thread. 要启用此功能,子级不能处于其他线程中。 Otherwise the parent might destroy an executing child, for example. 否则,例如,父母可能会破坏正在执行的孩子。

There are yet more catches, for example QPixmap cannot be in other thread than the main GUI etc. 还有更多的收获,例如,QPixmap不能位于主GUI等之外的其他线程中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM