Qt的界面线程 和Mfc 一点不一样的地方 引发我退群

king1076 2013-11-28 12:27:49
首先本人对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 就是二逼的设计。

上面的事 就献给和我一样 闲的蛋疼的人吧!
...全文
314 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
lm_whales 2014-01-19
  • 打赏
  • 举报
回复
QT 不清楚和线程安全有无关系
lm_whales 2014-01-19
  • 打赏
  • 举报
回复
win32界面相关的api不是线程安全的。 MFC的UI类,也因此不是线程安全的。 MFC使用CreateThread 和_beginthreadex 同样是危险的。 应该使用AfxBeginThread
江湖评谈 2014-01-19
  • 打赏
  • 举报
回复
QT不清楚,mfc tls控制线程的运行和识别。 你上面的过程应该封装在了线程状态中
encoderlee 2014-01-19
  • 打赏
  • 举报
回复
不仅仅是QT,MFC也要求只能由一个主线程来操作窗口。 把窗口指针传到新开的线程里,在线程里操作界面在MFC里也是不被允许的。 如果非要这样做的话也不是说就一定会出问题,只是说可能出现问题。 所以你写的那段MFC代码没有出问题,但在一个项目中大量这么用的话迟早要出问题。 所以不管是QT还是MFC,一般的做法都是工作线程通知主线程,由主线程来操作窗口。
worldy 2014-01-19
  • 打赏
  • 举报
回复
o牛的壳已经够重的了,还背了2个
king1076 2013-11-28
  • 打赏
  • 举报
回复
引用 1 楼 akirya 的回复:
首先在C\C++中用 CreateThread 是错误的 应换成_beginthreadex 其次 线程中不要直接操作UI线程的东西,win32界面相关的api不是线程安全的。 应该用PostThreadMssage或者SendMessage之类的发消息通知UI线程的东西。
恩恩,我知道beginthreadex! 上面只是小程序。 好主意 下次注意
  • 打赏
  • 举报
回复
首先在C\C++中用 CreateThread 是错误的 应换成_beginthreadex 其次 线程中不要直接操作UI线程的东西,win32界面相关的api不是线程安全的。 应该用PostThreadMssage或者SendMessage之类的发消息通知UI线程的东西。

1,649

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 非技术类
社区管理员
  • 非技术类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧