qt多线程编程
1. Qt多线程编程中子线程如何调用主线程中的成员变量
我提供两种比较简单的解决方案
创建一个Receiver的QObject, 该对象必须生存在你继承的线程中
要么给该对象构造对应的信号, 然后与你主线程窗体进行Connect, 一般来说是Queue的Connection
然后在子线程只要Emit你所实现的信号即可
或者用postEvent来解决, 自定义一种Event, 然后持有主线程窗体对象, 然后PostEvent给主线程窗体对象
2. QT多线程问题:子线程中的变量如何传递给主线程
public int _CurrentThread;
//form1_load中的,启动线程的代码在这里。
private void Form1_Load(object sender, EventArgs e)
{
//设置最大线程数
int MaxThread = 5;
//获取需要完成的任务列表
OleDbConnection AccessConn = AccessMole.Conn("D:\\Flying Co\\flying.mdb");
string sql = "select * from ty_task where bay_flag=" + false + " order by bay_id asc";
OleDbCommand comm = new OleDbCommand(sql, AccessConn);
OleDbDataReader list = comm.ExecuteReader();
while (list.Read())
{
ContentParse Spider = new ContentParse();
//如果当前活动线程超过最大线程数,线程休眠
if (Spider.CurrentThread> MaxThread)
{
Thread.Sleep(2000);
}
else
{
//init
Spider.Url = list["bay_task"].ToString();
//启动一个线程
Thread SpiderThread = new Thread(new ThreadStart(Spider.execute));
SpiderThread.Start();
MessageBox.Show(Spider.CurrentThread.ToString());
//任务设置为已处理
sql = "update ty_task set bay_flag=" + true + " where bay_id=" + list["bay_id"].ToString();
AccessMole.Execute(AccessConn, sql);
}
}
list.Close();
AccessMole.DisConn(AccessConn);
}
//线程启动的是这个类的方法
class ContentParse
{
private string _Url;
//设置任务参数
public string Url
{
set
{
_task = value;
}
}
public void execute()
{
//活动线程数加1
Interlocked.Increment(ref _CurrentThread);
//中间处理任务的代码省略
//该线程完成,活动线程减1
Interlocked.Decrement(ref _CurrentThread);
}
我现在纠结的就是这个Interlocked.Increment(ref _CurrentThread);应该是开一个线程就要加1的对吧?
但是我在form1中间用 MessageBox.Show(Spider.CurrentThread.ToString());,总是0噢
3. 各位QT大侠: QT多线程编程的时候,怎么把次线程处理好的数据实时的显示到ui上去
Qt上要求界面处理一般需要在主线程中完成。
所以最好把次线程中的数据缓冲区放到主线程中:
1、一种方式可以进行数据拷贝,但肯定效率低了。
2、另一种方式是直接将数据缓冲区放到主线程中,然后在主线程中处理读取数据槽。但这样可能主线程压力大,机器配置不能太低。
3、直接在主线程中访问次线程的数据并刷新界面,不过这处理起来复杂(需要手工同步),容易出错。
4、将TableWidget指针传入次线程中,直接在次线程中对其进行操作并发送刷新信号。这种方式未经验证,感觉可能性不大:一方面指针容易走空,另一方面就是前面说的限制在主线程中对接面进行处理。不过所说的“处理”可能并不包括刷新数据吧。
期待楼主进行验证,并展示结果。(或者楼主可以将UDP试验项目发送给我,让我试试,QQ:956693152,谢谢!)
4. Qt多线程绘制问题Cannot make QOpenGLContext current in a different thread
首先,创建QApplication实例前先开启Qt::AA_,有多个context的话还可以考虑开启Qt::AA_ShareOpenGLContexts。
其次,QOpenGLContext需要切换到使用线程才可以在那个线程make current,只需要调用其moveToThread即可。当然,context在多个线程间使用需要自行进行同步。
5. 如何对Qt中多线程系列进行限制和控制
浅析 Qt中多线程系列之线程初体验上篇 写了个线程的创建到运行的过程,可这还没完,线程创建完了之后必须要对其进行限制和控制,我们就是线程的监护人,不能说任由它自由,得对它进行合理约束。接下来我们讲线程的控制部分,
1、线程休眠
想象一下一种情形,日常用的电脑,如果我们需要离开一段时间,那么可能会将它暂时休眠一下,为了节约用电,也响应一下环境保护,别忘了现在都讲低炭生活。那么线程其实也一样,如果一个线程暂时不需要用到,我们可以先让它睡会,其目的也是为了让它暂时不要占用资源,主要是一个cpu时间片的占用问题。
对于线程的休眠,只要简单调用 Qthread 的sleep ,msleep或者usleep 方法就可以了,注意这三个方法都是Static Protected的,这意味着你只能在继承类里做这个动作,它们差别仅是时间单位不同而已。
程序方面我们尽量简单点,能看清本质就可以了,在Qthread 派生类的Run方法里面用下
1. void CThread::run()
2. {
3. for(int i=1;i<=10000;i++)
4. {
5. qDebug()<<i;
6. sleep(1); //请不要那么快,睡一下再往下执行
7. }
8. }
2、线程唤醒
既然有线程的休眠,那就有唤醒。如果你已经和线程说 Sleep 10秒吧,突然人家睡到一半的时候,你又改变主意想让它醒过来,这里我要抱歉的说声是没办法的,它就像猪一样,没到时间是不会醒的。比较合适的方案就是线程同步能够解决这样的问题,这个放到下一篇 线程的同步[1/2] 的时候再说.只要记住sleep是强制休眠就可以,但现在没办法提供强制唤醒的办法.
3、线程关闭
如果一个线程运行完了它会自己结束自己的生命。可很多情况不是这么简单,一个线程跑到中间的时候由于某种特殊原因,就想它中止。
(1)线程中止方式
中止有两种方式 强制中止和 优雅中止,这用词可能有点不恰当,先这么说着。在说明这两种方式之前,有必要详细说一下线程关闭的时候它到底干了什么。
线程关闭的时候,OS会移除这个线程,这部分对我们是透明的,详细的说明还得参阅操作系统的有关书籍,接着线程中分配的堆栈信息将一并清除,但是如果是堆上分配的信息,得由你负责自己清除,因为堆是由进程持有的,它的生命周期和线程没关系。
(2)强制中止:
简单的调用Qthread 的方法terminate就可以进行强制中止,可这将会带来很多灾难性的后果。最为严重的就是一个堆内存泄露的问题,线程强制被中止,根本没法来得及做清理工作,即使你的线程中有执行到最后清理堆内存,可它没来得及执行
比如以下一段代码
1. void CThread::run()
2. {
3. int *c = new int;
4. for(int i=1;i<=10000;i++)
5. {
6. qDebug()<<i;
7. }
8. //clean
9. delete c;
10. }
想象一下线程还没执行 到 delete c;的时候你就发出了terminate,不幸的事就发生了,由此得出结论我们应该尽最大限度避免去使用。
(3)优雅的中止:
那么怎么优雅的关闭线程呢?我们应该通知线程,让线程自己去接手关闭,各自关注自己所需的事,就都能做得更好,一手抓就会带来很多问题
那么怎么通知线程呢? 一般会采用以下的步骤
1.在Qthread中派生类 定义一个公用方法出来 供中止时调用,比如stop()
2.调用者 直接 调用stop方法
3.派生类stop方法 ,设置 中止标志,一般就是bool成员
4.run方法 运行的时候,检查bool成员,判断是否需要退出进程,最后做清理工作
1. //CThread.h
2. #ifndef CTHREAD_H
3. #define CTHREAD_H
4. #include <QThread>
5. class CThread : public QThread
6. {
7. public:
8. CThread();
9. ~CThread();
10. void stop();
11. protected:
12. void run();
13. private:
14. bool mStop;
15. };
16. #endif // CTHREAD_H
17.
18. //CThread.cpp
19. #include <QDebug>
20. #include "CThread.h"
21. CThread::CThread():QThread(),mStop(false)
22. {
23. }
24. CThread::~CThread()
25. {
26. stop();
27. }
28. void CThread::run()
29. {
30. int *c = new int;
31. for(int i=1;i<=10000;i++)
32. {
33. if (mStop) // determine to exit the loop
34. {
35. break;
36. }
37. qDebug()<<i;
38. sleep(1);
39. }
40. //clean up
41. delete c;
42. }
43. void CThread::stop()
44. {
45. mStop = true;
46. wait();
47. }
6. qt 怎么使用多线程遍历文件夹
一、Qt遍历文件夹下一层的文件:
方式1:
void ImageTree::addFolderImages(QString path)
{
//判断路径是否存在
QDir dir(path);
if(!dir.exists())
{
return;
}
dir.setFilter(QDir::Files | QDir::NoSymLinks);
QFileInfoList list = dir.entryInfoList();
int file_count = list.count();
if(file_count <= 0)
{
return;
}
QStringList string_list;
for(int i=0; i
{
QFileInfo file_info = list.at(i);
QString suffix = file_info.suffix();
if(QString::compare(suffix, QString("png"), Qt::CaseInsensitive) == 0)
{
QString absolute_file_path = file_info.absoluteFilePath();
string_list.append(absolute_file_path);
}
}
}
分析:遍历文件的下一层,对于系统而言包括:文件夹、文件、快捷方式,使用setFilter即可过滤。通过entryInfoList则可以获取过滤后所得到的文件夹下的文件信息列表,遍历文件通过操作QFileInfo可得到所需的文件详细信息(大小、类型、后缀等)。
7. Qt如何进行创建多线程
在Qt中使用多线程,目前就我使用过的有两种,一是子类化QThread,重写run函数,在run函数里实现自己的代码,这一部分代码通常是比较耗时,或者干脆直接阻塞的。比如一个while循环,设置一个标志,判断循环结束。
这样的例子在网上有很多,就不写了。
这样写的话,会有一些东西需要了解。
子类化QThread的方法,只有run函数里面的内容是执行在子线程里的,其他的部分,比如槽函数什么的还是在主线程里执行(假设是在主线程开启的该子线程)。
还有一种方法,是子类化QObject,新建一个线程,然后使用MoveToThread把这个类的对象移到新建的线程中,这种做法使得它所有的槽函数都是执行在新开辟的线程里面。
如果直接(QObject对象).abc()的话,这个成员函数是在主进程内执行,可能会出现"QObject::killTimer: timers
cannot be stopped from another thread"的运行错误。
使用第二种方法的话,貌似会遇到这样的问题:如果在一个槽函数中把子线程阻塞,其他的槽函数无法接受来自主线程
8. qt中connect 函数多线程怎么设置
项目中遇到了关于多线程编程问题
Class obj中有一个QTimer。线程A和线程B都有机会重启这个QTimer。
然而,在QT文档中QTimer并不是一个线程安全的类,因此就出现了怎样保证跨线程调用的安全性
首先,obj是是有线程概念的,它必须属于一个特定线程的(当然也可以使用moveToThread将它放入另外一个线程中,所有继承自QObject都有一个threadid的属性,用来标明此对象所属线程)
9. qt多线程编程里面怎么设置线程数
我学习QT的线程模块没多久。实现方案是继承QThread类,编写一个新的Thread线程类。
然后在主进程中要调用的时候就创建一个新的Thread并调用run函数启动线程。可以用数组存放这些thread,这样可方便主线程对这些线程的管理。