MFC线程创建运行关闭的问题
最近,由于論文的需求,要用到Windows下的多線程。考慮到界面用MFC寫 了,于是上網(wǎng)搜了下MFC下的多線程怎樣搞,都說用AfxBeginThread來日比較好。哥向來比較浮躁,先搜搜有沒相關(guān)代碼,找到幾個可用的,然后 各種摘抄,于是乎將哥的播放器的幾個線程搞成下面這段代碼(摘要):
UINT playThread(LPVOID pParam){??//播放線程,固定格式
????//......做變量聲明,賦值等前期工作
????while(SomeCondition){?????? //播放線程的循環(huán)
??????????//......播放音樂,不解析
????}
????return 0;
}
void CPlayerDlg::OnBnClickedPlay(){?? //播放按鈕響應(yīng)函數(shù)
????if(isThreadPause){?? //判斷是否暫停中
????????isThreadPause=false;
????????pPlayerThread->ResumeThread();//繼續(xù)播放
????}
????else{
????????OnBnClickedStop();
????????pPlayerThread=AfxBeginThread(playWaveThread,NULL);??//開啟播放線程
????}
}
void CPlayerDlg::OnBnClickedPause(){???? //暫停響應(yīng)函數(shù)
????if(!isThreadPause){
????????PlayerThread->SuspendThread();???? //掛起進(jìn)程,相當(dāng)于暫停播放
????????isThreadPause=true;
????}
}
void CPlayerDlg::OnBnClickedStop(){????//終止響應(yīng)函數(shù)
????if(pPlayThread){
????????isThreadPause=false;
????????TerminateThread(pPlayerThread->m_hThread,0);//強(qiáng)行終止線程,這里有問題,后面說
????}
}
其中播放線程playThread的聲明是固定那種格式的,而且最好寫成全局函數(shù),方便,如果寫成類成員函數(shù)的話又要加static,調(diào)用時又要加作用域的,十分蛋痛。寫完后果斷運(yùn)行,yeah,能播放、暫停和停止,相當(dāng)舒服,也沒去理會細(xì)節(jié)的問題。
直到今天,心血來潮地打開任務(wù)管理器,看看程序內(nèi)存占用情況,發(fā)現(xiàn)了一個狠嚴(yán)重的問題:每當(dāng)我停止一首歌,播放下一首時,內(nèi)存就突然間往上跳。 一開始以為是正常的內(nèi)存創(chuàng)建和回收造成的浮動,但我繼續(xù)不斷地重復(fù)播放停止、播放停止,發(fā)現(xiàn)內(nèi)存一直往上升。雖然每次都只是上升一點點,但明擺著的 memory leak擱在那,還不搞它哥以后怎樣出來混?
好,果斷google之,發(fā)現(xiàn)問題出在TerminateThread這個函數(shù)。這個TerminateThread結(jié)束線程用的是相當(dāng)暴力的 方法,據(jù)說連里面的局部變量都不釋放。這就草了,馬上尋找解決辦法,有人回帖說用CreateEvent和WaitForSingleObject結(jié)合日 之,解釋沒解釋清楚,給出的sample code也是相當(dāng)糾結(jié)和羞澀,而且樓下跟帖說這種方法有可能阻塞死鎖之類的。果斷放棄,看 到另外一種方法,就是在停止的響應(yīng)函數(shù)里用::PostThreadMessage(由于播放線程是全局函數(shù),所以前面要加::)給播放線程發(fā)送停止消 息,播放線程里加一個MSG的變量和while,每次里面調(diào)用PeekMessage來檢查是否發(fā)來停止的消息,寫了下,代碼相當(dāng)簡練明了:
#define WM_THREAD_STOP 0x0427?? //自定義一個消息,也可以用系統(tǒng)定義的如WM_QUIT
UINT playWaveThread(LPVOID pParam){
????//......做變量聲明,賦值等前期工作
????while(SomeCondition){?????? //播放線程的循環(huán)
????????MSG msg;?? //增加一個MSG的變量msg來接收消息
????????while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)){??????//將消息隊列里的消息逐個讀入msg
????????????if(msg.message==WM_THREAD_STOP){???? //如果收到終止消息則退出
????????????????//TODO:放在堆里的變量要在這里手動清理
????????????????return 0;??????//線程正常返回,會釋放局部變量等內(nèi)存資源
????????????}
????????????else{
????????????????DispatchMessage(&msg);//字面意思,不解釋
????????????}
????????}
?????????????? //......播放音樂,不解析
????}
????return 0;//正常播放結(jié)束,釋放資源
}
void CPlayerDlg::OnBnClickedPlay(){……}//播放按鈕響應(yīng)函數(shù),不變
void CPlayerDlg::OnBnClickedPause(){……}//暫停響應(yīng)函數(shù),也不變
void CPlayerDlg::OnBnClickedStop(){
????if(pPlayerThread){
????????isThreadPause=false;
????????//原來的TerminateThread不用,換成下面這個
????????::PostThreadMessage(pPlayerThread->m_nThreadID,WM_THREAD_STOP,0,0);
????}
}
寫完,果斷運(yùn)行并打開任務(wù)管理器監(jiān)測,誒!果然沒有出現(xiàn)之前的內(nèi)存一直在漲的現(xiàn)象,十分舒服,搞定收工!話說本人剛學(xué)多線程,代碼寫得相當(dāng)?shù)乃?#xff0c;如果哪位大牛看到這處理方法還存在什么問題望不吝賜教,謝謝!
總結(jié)
以上是生活随笔為你收集整理的MFC线程创建运行关闭的问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 各类音频格式解析
- 下一篇: mfc 创建线程函数AfxBeginTh