سؤال

I want to run two threads concurrently. I successfully did the same when I ran a program as a QT console application. Here's the working code of QT console application for multi threading:-

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:

#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

#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. 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

#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.

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. 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.

Another catch in multithreading in Qt is the fact that any QObject cannot reside in different thread than its parent. 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.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top