【引用】如何结束线程运行(转)

简介: 【引用】如何结束线程运行(转)

在一些应用程序中,除非用户去结束应用程序的运行,否则其中的子线程会一直处于运行状态。如果应用程序在结束时不主动通知子线程退出,有可能导致主线程结束后,子线程的系统资源得不到释放。如何通知子线程结束运行呢?这需要在程序设计阶段就考虑到,通常可以用事件、消息或全局变量来通知子线程退出运行循环或消息循环。消息通知方式适合用来通知有消息循环的用户界面线程退出,但理论上讲消息机制是不可靠的(消息可能会丢失,尽管可能性很小);事件通知的方式及时并且可靠,在应用程序准备结束运行前,设置一个通知事件;子线程的运行循环中不断检查通知事件,一旦发现事件信号设置,就可以退出循环,从而结束子线程的运行。主线程在设置通知事件后,不能马上退出,而应该等待子线程先结束后再退出。等待子线程结束方法很多,例如使用循环(while或 WM_CLOSE消息循环)检测线程状态等待,WaitForSingleObject函数等待,还有Sleep函数等待等,但有些方法在使用时可能导致线程死锁,因而必须小心。

举例来说,一个子线程不断将自己的处理进度刷新到对话框的进度条控件,这里刷新对话框事实上有赖于主线程的消息循环来处理刷新消息;如果用户不等处理结束就点击关闭对话框按钮,而主线程设置通知事件后如果使用WaitForSingleObject函数等待子线程结束的话,极可能导致线程死锁。因为 WaitForSingleObject函数会将主线程挂起(任何消息都得不到处理)直到子线程结束事件发生;而子线程可能正在设置进度条,一直在等待主线程将刷新消息处理完毕返回才会检测通知事件。于是,死锁发生了,应用程序"死"在那里无法自动结束,必须靠任务管理器将其强制结束(可能造成该程序的资源和内存得不到释放)。

采用循环检测的方法比较安全些,但while循环本身可能会导致主线程乃至子线程阻塞,子线程也因得不到及时调度而迟迟难以结束,应用程序界面可能半天都没有响应。当子程序结束需要较长时间时,这是很令人厌恶的。不过,可以通过在while循环中加入Sleep(10~50)主动释放CPU占用来促使子线程得到调度,也可以通过调高子线程的优先级来促使其尽快结束。而通过在WM_CLOSE消息处理函数中检测子线程状态的方法最值得推荐,该方法既不会挂起主线程,也不会阻塞子线程。检测如果发现子线程仍然在活动状态,就再此向主窗口发送一个WM_CLOSE消息,以便再次进入该消息处理函数检查子线程状态,直到子线程结束为止。

下面是等待线程结束的示例代码:

void CProgressDlg::OnClose()
{
        DWORD   dwStatus;
        if (m_pWorkerThread != NULL)
        {
               VERIFY(::GetExitCodeThread(m_pWorkerThread ->m_hThread, &dwStatus));
               if (dwStatus == STILL_ACTIVE)
               {
                      ::SetEvent(g_hEventKill); // 通知子线程结束运行
                // 调高子线程优先级
   m_pWorkerThread->SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL);
                      PostMessage(WM_CLOSE); // 给本窗口再发一个结束消息
                      Return;
               }
               else
               {
                      delete m_pWorkerThread;
                      m_pWorkerThread = NULL;
               }
        }
        CDialog::OnClose();
}
        CDialog::OnClose();
}
相关文章
|
安全 Java
【JavaSE专栏76】三态和五态,线程的不同状态:新建、运行、状态、阻塞、等待、计时等待状态
【JavaSE专栏76】三态和五态,线程的不同状态:新建、运行、状态、阻塞、等待、计时等待状态
102 0
|
消息中间件 缓存 Kafka
连Producer端的主线程模块运行原理都不清楚,就敢说自己精通Kafka?
连Producer端的主线程模块运行原理都不清楚,就敢说自己精通Kafka?
58 0
|
安全 算法 Java
去某东面试遇到并发编程问题:如何安全地中断一个正在运行的线程
一个位5年的小伙伴去某东面试被一道并发编程的面试题给Pass了,说”如何中断一个正在运行中的线程?,这个问题很多工作2年的都知道,实在是有些遗憾。 今天,我给大家来分享一下我的回答。
94 0
|
3月前
|
编解码 网络协议 API
Netty运行原理问题之Netty的主次Reactor多线程模型工作的问题如何解决
Netty运行原理问题之Netty的主次Reactor多线程模型工作的问题如何解决
|
2月前
|
Java Spring
运行@Async注解的方法的线程池
自定义@Async注解线程池
159 3
|
3月前
|
消息中间件 设计模式 安全
多线程魔法:揭秘一个JVM中如何同时运行多个消费者
【8月更文挑战第22天】在Java虚拟机(JVM)中探索多消费者模式,此模式解耦生产与消费过程,提升系统性能。通过`ExecutorService`和`BlockingQueue`构建含2个生产者及4个消费者的系统,实现实时消息处理。多消费者模式虽增强处理能力,但也引入线程安全与资源竞争等挑战,需谨慎设计以确保高效稳定运行。
93 2
|
4月前
|
安全 开发者
LabVIEW程序退出后线程仍在运行问题
LabVIEW程序退出后线程仍在运行问题
52 2
|
5月前
|
Java 程序员
Java多线程编程是指在一个进程中创建并运行多个线程,每个线程执行不同的任务,并行地工作,以达到提高效率的目的
【6月更文挑战第18天】Java多线程提升效率,通过synchronized关键字、Lock接口和原子变量实现同步互斥。synchronized控制共享资源访问,基于对象内置锁。Lock接口提供更灵活的锁管理,需手动解锁。原子变量类(如AtomicInteger)支持无锁的原子操作,减少性能影响。
46 3
|
5月前
|
Java
【技术解码】Java线程的五味人生:新建、就绪、运行、阻塞与死亡的哲学解读!
【6月更文挑战第19天】Java线程生命周期如同人生旅程,经历新建、就绪、运行、阻塞至死亡五阶段。从`new Thread()`的诞生到`start()`的蓄势待发,再到`run()`的全力以赴,线程在代码中奔跑。阻塞时面临挑战,等待资源释放,最终通过`join()`或中断结束生命。线程的每个状态转变,都是编程世界与哲思的交汇点。
39 1
|
5月前
|
Dart Serverless Android开发
Flutter 单线程模型保证UI运行流畅
Flutter 单线程模型保证UI运行流畅
73 0