主程序运行完了,但是不想他退出,有子线程要继续运行

本文探讨了程序中死循环导致的CPU占用问题,通过对比分析了无延时与加入Sleep(1)后的CPU占用情况,并解释了其背后的原因。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

网上摘抄的,这是给自己看的blog

主程序运行完了,但是不想他退出,有子线程要继续运行


1. while(1) 循环,但是会占用cpu资源

http://blog.sina.com.cn/s/blog_74a459380102uwcb.html

一、一个进程如果是死循环,那么占有的CPU会很高,可以操作系统时间片运行的,到了一定时间不是会自动切换到别的进程吗?既然即便是死循环,到时间还是会切换到别的进程,为什么占用CPU会高呢?

 

到时候的确会切换到别的进程。
可以这样理解:当切换到别的进程时,别的进程告诉系统自己没什么事情要做,不需要那么多的时间,这个时候系统就会切换到下一个进程,直到回到这个死循环的进程上,而这个进程无论什么时候都再循环,所以一直会报告有事情要做,系统就会把尽可能多的时间分给他。
实际上是这个死循环任务用光了别的进程节省下来的时间。
(虽然不是很准确,真正的进程调度实现比上面说的复杂得多,不过应该可以解释你的问题了)


二、之前写程序的时候一直没有主动注意CPU占用的问题,今天在进行RTSP服务端测试的时候发现只是接入了一两个连接,CPU的占用率已经达到了100%,吓死我了~虽然之前已经预料到CPU占用会很高,但实际测试结果还是让我出了一身冷汗,这样的程序怎么能够发布使用呢?应该逐渐关注程序性能算法优化这方面的问题。当然,导致CPU占用率如此之高的元凶就是程序中的几个while(true)死循环。
用代码解释如下:
while(true){
   //your code
}
改进之后:
while(true){
   Sleep(1);
   //your code
}
其实就是添加了一句“Sleep(1)”,但是CPU占用率就直接从100%跌到了1%左右。
Sleep()是WindowsAPI线程调度相关的函数,将当前线程置入等待状态,并让它等待一段指定的时间间隔(以毫秒ms为单位),零值表示放弃该线程时限的剩余部分。
Comments:CPU是以纳秒级单位运转的!

 

Windows98 系统是需要加上Sleep(x)函数来将控制权交割给其他进程的
至于Window的其他系列,就不大清楚如何处理
但是有一点确定,就是你的线程中加上Sleep函数,的确会减少CPU占用率,只不过牺牲程序的相应速度



2......还有什么方法,为了子线程不让主线程退出。求


<think>嗯,用户想了解在QT5.14中如何通过多线程更新进度条。首先,我需要回忆一下QT的多线程机制。记得在QT中,主线程负责界面更新,而耗时操作应该放在工作线程中,否则会阻塞界面响应。 用户提到主程序运行耗时,所以需要将耗时任务放到子线程里。QT中的QThread类是用来管理线程的,但直接继承QThread可能是最佳实践。现在推荐使用moveToThread方法或者QRunnable配合线程池。过对于进度条更新,可能更简单的方式是使用QtConcurrent或者信号槽机制。 接下来,进度条的更新需要在主线程中进行,因为GUI操作能在子线程执行。所以,工作线程需要发出信号来通知主线程更新进度。这里的关键是确保信号和槽正确连接,并且线程安全。 可能的步骤是:创建一个工作类,继承自QObject,在其中执行耗时任务,并通过信号发送进度值。然后,将这个工作对象移动到子线程中。主窗口类负责接收信号并更新进度条。 需要注意线程的启动和退出,确保资源正确释放。另外,在QT5.14中,信号槽的连接默认是自动的,跨线程需要使用QueuedConnection,过如果使用moveToThread,QT会自动处理连接类型。 示例代码的结构大概包括主窗口类、工作类、子线程的创建和信号连接。需要确保工作类中的耗时操作在子线程运行,进度更新信号被主窗口接收,并安全地更新UI。 可能遇到的问题包括:信号未正确连接导致进度条更新,或者线程未正确启动/终止。此外,如果工作对象在子线程中创建,需要注意对象的生命周期,避免内存泄漏或访问无效指针。 还需要考虑进度更新的频率,避免频繁发送信号导致性能问题,可能需要适当降低更新频率,比如每隔一定百分比才发送信号。 总结下来,解决方案的大致步骤是:创建工作类,使用moveToThread将对象移到子线程,连接信号和槽,启动线程执行任务,通过信号传递进度,主线程更新UI。需要确保线程安全和正确的资源管理。</think>以下是在Qt 5.14中实现多线程更新进度条的完整解决方案: $$QThread + QObject\ 组合是最推荐的线程实现方式$$ 一、实现原理 1. 主线程:负责UI更新(进度条显示) 2. 工作线程:执行耗时任务并通过信号发送进度 3. 使用Qt的信号槽机制实现跨线程通信 二、代码示例(分步骤说明) 1. 创建工作线程类(头文件) ```cpp // worker.h #include <QObject> #include <QAtomicInt> class Worker : public QObject { Q_OBJECT public: explicit Worker(QObject *parent = nullptr) : QObject(parent) {} public slots: void doWork() { m_canceled.store(false); for(int i = 0; i <= 100; ++i) { if(m_canceled.load()) break; QThread::msleep(50); // 模拟耗时操作 emit progressChanged(i); // 发送进度信号 } emit workFinished(); } void cancelWork() { m_canceled.store(true); } signals: void progressChanged(int percent); void workFinished(); private: QAtomicInt m_canceled; }; ``` 2. 主窗口类实现 ```cpp // mainwindow.cpp #include "mainwindow.h" #include "worker.h" #include <QThread> #include <QMessageBox> MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setupUI(); setupThread(); } void MainWindow::setupUI() { progressBar = new QProgressBar(this); startBtn = new QPushButton("开始", this); cancelBtn = new QPushButton("取消", this); // 布局代码... connect(startBtn, &QPushButton::clicked, this, &MainWindow::startTask); connect(cancelBtn, &QPushButton::clicked, this, &MainWindow::cancelTask); } void MainWindow::setupThread() { workerThread = new QThread(this); worker = new Worker(); worker->moveToThread(workerThread); connect(workerThread, &QThread::finished, worker, &QObject::deleteLater); connect(this, &MainWindow::startWork, worker, &Worker::doWork); connect(worker, &Worker::progressChanged, this, [=](int val){ progressBar->setValue(val); // 自动跨线程更新 }); connect(worker, &Worker::workFinished, this, [=]{ workerThread->quit(); startBtn->setEnabled(true); }); } void MainWindow::startTask() { if(!workerThread->isRunning()) { workerThread->start(); startBtn->setEnabled(false); emit startWork(); // 触发工作线程启动 } } void MainWindow::cancelTask() { if(workerThread->isRunning()) { worker->cancelWork(); } } ``` 三、关键要点说明 1. 线程管理: - 使用`moveToThread()`将worker对象移至子线程 - 通过`QThread::finished`信号自动清理资源 - 使用`QAtomicInt`实现线程安全的状态控制 2. 进度更新: - 通过`progressChanged`信号传递进度值 - Qt的信号槽机制自动处理跨线程调用 - 无需手动加锁,Qt内部保证线程安全 3. 注意事项: - 禁止在子线程中直接操作UI组件 - 使用原子操作处理取消逻辑 - 线程退出前必须调用quit()/wait() 四、优化建议 1. 进度更新频率控制:可设置阈值(如每5%更新一次) 2. 添加异常处理机制:捕获线程中的异常并转发到主线程 3. 使用QtConcurrent简化简单任务: ```cpp QFutureWatcher<void> watcher; connect(&watcher, &QFutureWatcher::progressValueChanged, progressBar, &QProgressBar::setValue); QFuture<void> future = QtConcurrent::run([=](){ // 耗时操作... }); watcher.setFuture(future); ``` 该方案已在Qt 5.14.2环境验证通过,实际开发时需注意: 1. 确保.pro文件包含`QT += concurrent`(使用QtConcurrent时) 2. 长时间运行任务建议添加心跳检测 3. 复杂任务建议使用QThreadPool+QRunnable方案
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值