Qt的界面線程 和Mfc 一點不一樣的地方

首先本人對Qt不是太瞭解,但是不想僅僅停留在用的角度上。

開發平臺:windows

由於軟件要寫成多線程版本的,界面會用到MFC,QT,或者沒有界面只是控制檯。

我當時想的是:

底層API + MFC
底層API + QT
底層API + 控制檯

但是我在QT的界面上卡住了,由於我不想用QT的線程,我想在底層上用win32的線程處理好了,再用MFC和QT用,畢竟我只用他們來寫界面。

上午的時間好氣人,我在一個Qt的羣裏面討論我說了下思路: 創建線程的時候傳遞一個Qt的類參數。有個人說 win32 + qt是二逼的設計,當場老子控制不住了 你以爲自己會用Qt就了不起了,Qt還不是封裝的win32的API,還叫我用開源的線程庫 我挺無語的!當場退了這個羣,和這種人在一塊,智商會變低!

我操,還偷偷看老子的空間,難道這是要報復的節奏?

算了不說了,說下QT界面 和MFC界面上線程的一點區別,原理性的我不清楚,目前能找到的線索,我先列出來!

Qt方案:


#ifndef MAINWINDOW_H

#define MAINWINDOW_H

#include <QMainWindow>

#include <windows.h>

#include <QDebug>

#include "myobject.h"

namespace Ui {

class MainWindow;

}

class MainWindow : public QMainWindow

{

    Q_OBJECT

    

public:

    explicit MainWindow(QWidget *parent = 0);

    ~MainWindow();

    static int threadFunc(void* _data);

signals:

    void start();

private slots:

    void on_pushButton_clicked();

    void on_pushButton_2_clicked();

    void Run();

    void Run(int pos);

    void on_pushButton_3_clicked();

private:

    MyObject obj;

    Ui::MainWindow *ui;

    HANDLE thread;

    bool bExit;

};

#endif // MAINWINDOW_H


#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    bExit = false;
    connect(this,SIGNAL(start()),this,SLOT(Run()));
    connect(&obj,SIGNAL(start(int)),this,SLOT(Run(int)));
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::Run(int pos){
        ui->progressBar->setValue(pos);
    qDebug()<<GetCurrentThreadId()<<endl;
}
void MainWindow::Run(){
    while(!bExit)
    {
        for(int i=0;i<100;i++){
        ui->progressBar->setValue(i);
        Sleep(1000);
        }
    }
    qDebug()<<GetCurrentThreadId()<<endl;
}

int MainWindow::threadFunc(void* _data){
    MainWindow* m = (MainWindow*)_data;
    m->Run();
    return 0;
}

void MainWindow::on_pushButton_clicked()
{
    thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)threadFunc,this,0,0);
    qDebug()<<GetCurrentThreadId();
}

void MainWindow::on_pushButton_2_clicked()
{
    bExit= true;
}

void MainWindow::on_pushButton_3_clicked()
{
    obj.Start();
}

這是一個簡單的測試。我想在線程中 讓進度條 走動

測試內部線程 是:在Qt的這個界面中 創建一個win32 線程,將界面的指針傳過去,在新的線程函數中 處理進度條。但是這樣出問題了,錯誤提示如下

大致意思 是界面線程 和新的線程 不在一個線程中 不能操作。那就輸出下線程ID吧:

主線程:6196
副線程:7199

果然不一樣

剛開始有點疑惑,因爲在MFC下不會出現這種情況,也許是還沒有從MFC的思路中走出來吧?但是問題還是要解決的要不然 完不成任務。

間接線程:這個是我想的另一個解決方案。

我創建了另一個集成QObject的子類:

#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <QObject>
#include <Windows.h>
class MyObject : public QObject
{
    Q_OBJECT
public:
    explicit MyObject(QObject *parent = 0);
    
signals:
    void start(int pos);
public:
    void Start();
    HANDLE thread;
    static int mythread(void* data);
public slots:
    
};

#endif // MYOBJECT_H

#include "myobject.h"

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

}
int MyObject::mythread(void* data)
{
    MyObject* obj = (MyObject*)data;
    for(int i=0;i<1000;i++){
        emit obj->start(i);
    }
    return 0;
}

void MyObject::Start(){
  thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)mythread,this,0,0);
}
中間類中 有一個信號 和主界面的槽鏈接,我在這個中間類中創建一個WIN32 線程,在線程函數中 發送信號 給主界面的槽。oK沒有問題。程序沒有報錯;看來QT的界面操作必須要在一個線程中,纔可以嗎?求高人指點!


下面我們看MFC的:

MFC的代碼太多了,就不貼了,思路和QT的方案1 一樣。

先輸出 線程的ID吧

副線程9632
主線程9596
主要代碼:

void CthreadtestDlg::OnBnClickedButton1()
{
	// TODO: 在此添加控件通知處理程序代碼
	thread = CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)threadfunc,this,0,0);
	TRACE("主線程%d\n",GetCurrentThreadId());
}
int CthreadtestDlg::threadfunc(void* data){
	
	TRACE("副線程%d\n",GetCurrentThreadId());
	CthreadtestDlg* dlg = (CthreadtestDlg*)data;
	dlg->Run();
	return 0;
}
void CthreadtestDlg::Run(){
	for(int i=0;i<100;i++)
		m_progress.SetPos(i);
}
但是在 MFC上沒有出現問題。不知道爲什麼?

雖然底層原理 我不是太明白,但是起碼 我想知道爲什麼。而不是說 一看win32+ QT 就是二逼的設計。

上面的事 就獻給和我一樣 閒的蛋疼的人吧!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章