摘自http://www.cnblogs.com/busuncle/archive/2010/05/17/1737467.html
MFC下结束AfxBeginThread开启的线程的一些体会
最近,由于论文的需求,要用到Windows下的多线程。考虑到界面用MFC写 了,于是上网搜了下MFC下的多线程怎样搞,都说用AfxBeginThread来日比较好。哥向来比较浮躁,先搜搜有没相关代码,找到几个可用的,然后 各种摘抄,于是乎将哥的播放器的几个线程搞成下面这段代码(摘要):
UINT playThread(LPVOID pParam){ //播放线程,固定格式
//......做变量声明,赋值等前期工作
while(SomeCondition){ //播放线程的循环
//......播放音乐,不解析
}
return 0;
}
void CPlayerDlg::OnBnClickedPlay(){ //播放按钮响应函数
if(isThreadPause){ //判断是否暂停中
isThreadPause=false;
pPlayerThread->ResumeThread();//继续播放
}
else{
OnBnClickedStop();
pPlayerThread=AfxBeginThread(playWaveThread,NULL); //开启播放线程
}
}
void CPlayerDlg::OnBnClickedPause(){ //暂停响应函数
if(!isThreadPause){
PlayerThread->SuspendThread(); //挂起进程,相当于暂停播放
isThreadPause=true;
}
}
void CPlayerDlg::OnBnClickedStop(){ //终止响应函数
if(pPlayThread){
isThreadPause=false;
TerminateThread(pPlayerThread->m_hThread,0);//强行终止线程,这里有问题,后面说
}
}
其中播放线程playThread的声明是固定那种格式的,而且最好写成全局函数,方便,如果写成类成员函数的话又要加static,调用时又要加作用域的,十分蛋痛。写完后果断运行,yeah,能播放、暂停和停止,相当舒服,也没去理会细节的问题。
直到今天,心血来潮地打开任务管理器,看看程序内存占用情况,发现了一个狠严重的问题:每当我停止一首歌,播放下一首时,内存就突然间往上跳。 一开始以为是正常的内存创建和回收造成的浮动,但我继续不断地重复播放停止、播放停止,发现内存一直往上升。虽然每次都只是上升一点点,但明摆着的 memory leak搁在那,还不搞它哥以后怎样出来混?
好,果断google之,发现问题出在TerminateThread这个函数。这个TerminateThread结束线程用的是相当暴力的 方法,据说连里面的局部变量都不释放。这就草了,马上寻找解决办法,有人回帖说用CreateEvent和WaitForSingleObject结合日 之,解释没解释清楚,给出的sample code也是相当纠结和羞涩,而且楼下跟帖说这种方法有可能阻塞死锁之类的。果断放弃,看 到另外一种方法,就是在停止的响应函数里用::PostThreadMessage(由于播放线程是全局函数,所以前面要加::)给播放线程发送停止消 息,播放线程里加一个MSG的变量和while,每次里面调用PeekMessage来检查是否发来停止的消息,写了下,代码相当简练明了:
#define WM_THREAD_STOP 0x0427 //自定义一个消息,也可以用系统定义的如WM_QUIT
UINT playWaveThread(LPVOID pParam){
//......做变量声明,赋值等前期工作
while(SomeCondition){ //播放线程的循环
MSG msg; //增加一个MSG的变量msg来接收消息
while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)){ //将消息队列里的消息逐个读入msg
if(msg.message==WM_THREAD_STOP){ //如果收到终止消息则退出
//TODO:放在堆里的变量要在这里手动清理
return 0; //线程正常返回,会释放局部变量等内存资源
}
else{
DispatchMessage(&msg);//字面意思,不解释
}
}
//......播放音乐,不解析
}
return 0;//正常播放结束,释放资源
}
void CPlayerDlg::OnBnClickedPlay(){……}//播放按钮响应函数,不变
void CPlayerDlg::OnBnClickedPause(){……}//暂停响应函数,也不变
void CPlayerDlg::OnBnClickedStop(){
if(pPlayerThread){
isThreadPause=false;
//原来的TerminateThread不用,换成下面这个
::PostThreadMessage(pPlayerThread->m_nThreadID,WM_THREAD_STOP,0,0);
}
}
写完,果断运行并打开任务管理器监测,诶!果然没有出现之前的内存一直在涨的现象,十分舒服,搞定收工!话说本人刚学多线程,代码写得相当的水,如果哪位大牛看到这处理方法还存在什么问题望不吝赐教,谢谢!
相关推荐
`AfxBeginThread`是MFC提供的一个方便的函数,用于直接创建线程实例,它是基于CWinThread类的。本文将深入探讨如何使用`AfxBeginThread`来创建线程,以及在MFC应用程序中如何管理和通信。 1. **AfxBeginThread的...
下面将详细讨论`AfxBeginThread`的使用、工作线程的概念、多线程编程的重要性以及MFC中的线程通信。 1. **`AfxBeginThread`函数详解** `AfxBeginThread`是MFC中的一个静态成员函数,位于`CWinThread`类中。它用于...
总结来说,虽然`BeginThread`在某些情况下可能更为灵活,但在MFC环境中,推荐使用`AfxBeginThread`,因为它能更好地集成MFC框架,简化线程的生命周期管理。在创建工作者线程时,确保线程函数具有正确的返回类型(`...
`AfxBeginThread`的优点在于它简化了线程的创建过程,自动处理了线程的初始化和清理工作,并且能够更好地与MFC类库集成。使用`AfxBeginThread`时,你需要提供一个CWinThread派生类的实例,该类包含线程执行的代码。...
总结起来,VS2019中的MFC线程创建涉及到创建自定义线程类、覆写关键成员函数、使用 `AfxBeginThread()` 创建线程以及进行线程同步。理解这些概念和实践,对于开发高效、稳定的多线程MFC应用至关重要。
MFC线程默认通过`CWinThread::ExitInstance()`函数来结束其执行,该函数会减少线程计数,并调用`OnExit()`成员函数,允许用户进行清理工作。但仅调用`ExitInstance()`可能不足以保证线程的安全退出,因为资源释放...
本主题将深入探讨如何在MFC框架下实现多线程技术。 **MFC中的线程** MFC支持两种类型的线程:用户界面(UI)线程和工作线程。UI线程负责与用户交互,而工作线程通常用于执行后台计算或长时间运行的任务,以避免阻塞...
默认情况下,MFC应用程序会为主线程创建一个消息循环,但当创建新线程时,这个新线程不会自动包含消息循环。因此,为了在线程中处理这些消息,我们需要手动为线程添加自定义的消息循环。 要在线程中创建自定义的...
标题"**DuoXianCheng.rar_MFC_MFC多线程_MFC多线程例子_MFC界面线程_mfc 多线程**"暗示了我们将会讨论如何在MFC应用程序中实现多线程,特别是涉及到UI(用户界面)线程的管理。 MFC是微软为Windows平台开发的应用...
1. **线程创建**:在MFC中,可以使用`AfxBeginThread`函数创建一个新的线程。这个函数需要一个类指针,该类继承自`CWinThread`。创建线程时,需要指定线程的优先级和初始堆栈大小。 2. **工作者线程类**:你需要...
本文将详细介绍如何在MFC中创建、挂起和结束线程,以及相关操作。 一、创建线程 在MFC中,创建线程通常通过继承`CWinThread`类来实现。首先,你需要创建一个新的类,比如`CMycustomThread`,并让它继承自`...
总结,MFC编写的用户界面多线程小例子是一个很好的学习资源,它演示了如何在MFC应用程序中实现多线程,以及如何在多线程环境下有效地管理用户界面。通过深入理解这个例子,开发者可以更好地掌握MFC和多线程编程,...
MFC 提供了一些类和函数来帮助开发者实现多线程编程,例如 CWinThread 类和 AfxBeginThread 函数。 MFC 多线程编程是提高程序执行效率和响应速度的有效手段,可以实现并行处理,避免了某项任务长时间占用 CPU 时间...
总结来说,这个项目是关于如何在MFC环境下,利用CWinThread类创建异步多线程的串口通信程序。对于新手来说,这是一个很好的起点,可以帮助他们理解串口通信的基本原理和多线程编程技术。通过实践这个示例,开发者...
3. 使用`AfxBeginThread`函数来创建并启动工作者线程,传递线程类的实例和适当的参数。 工作者线程与UI线程之间的通信需要注意同步问题,以防止数据竞争和死锁。MFC提供了多种同步机制,如`CSemaphore`(信号量)、...
MFC线程可以通过调用`ExitThread`函数来结束自己的运行,或者在主线程中调用`WaitForSingleObject`或`WaitForMultipleObjects`来等待线程结束。 6. **线程优先级** 线程优先级决定了操作系统调度线程执行的顺序。...
`AfxBeginThread`是MFC提供的一个方便的函数,用于创建线程,它会自动处理一些MFC特定的初始化工作,如设置消息循环和线程局部存储。然而,如果你选择使用`CreateThread`,你需要手动处理这些细节,这通常意味着更多...
在本文中,我们将深入探讨如何使用Microsoft Foundation Class (MFC) 库以及Visual Studio 2005在C++环境中实现多线程编程。MFC是微软为Windows平台开发的一个C++类库,它提供了丰富的功能,使得创建Windows应用程序...