關於多執行緒的一些細節 (轉)

worldblog發表於2007-12-06
關於多執行緒的一些細節 (轉)[@more@]

關於多執行緒的一些細節


  作者: coolnerd


  執行緒的中,如果執行緒要向介面視窗報告狀態,有兩種操作方法,
一種是透過訊息的方法,由於訊息本身攜帶的訊息量有時不購用,往往訊息引數
只是一個指向某訊息的指標,而訊息物件往往需要在堆中new生成,

(因為往往執行緒不能等待訊息處理完畢就繼續,所以如果訊息物件是棧物件
往往訊息物件還未來及被處理,就又被執行緒修改.所以採用堆物件.)

介面接受到
訊息物件後delete之.但是這時介面退出後,如果執行緒仍然生成新的訊息物件,
則訊息物件得不到釋放,所以在這種情況下,介面接受到WM_CLOSE訊息將要釋放
之前,要等待執行緒完全退出之後再真正釋放.

執行緒向介面報告狀態的第二種方法是直接線上程的執行過程中同步地(等待,
直到完成稱為同步)執行介面顯示,這種機制下,要注意在介面顯示是需要檢視
介面視窗是否仍然存在(使用IsWindow(hWnd)實現).
這樣做似乎已經完美,但是是不完善的,因為假如有多個view小視窗,如多個
CSplitterWnd,只在一個CSplitterWnd的WM_CLOSE訊息的處理函式中進行防範,
其他的CSplitterWnd照常退出,仍然要出問題,所以要抓住根源:

使用選單退出或點選frmae視窗的x按鈕退出,接受到退出訊息的首先是frameWnd
所以需要在frameWnd的WM_CLOSE函式中進行執行緒的釋放.!
另外,往往執行緒在Document類的掌管之下,frame怎樣訪問document物件?
FrameWnd沒有直接提供獲取document的函式.Document,View,FrameWnd三者的
建立順序是:doc->Frmae->View,在View::InitUpdate()函式的執行時刻,
可以執行以下程式碼:
CMainFrame*frm=(CMainFrame*)(AfxGetApp()->m_pMainWnd);
frm->pDoc=GetDocument();
另外:注意需要捕捉WM_CLOSE,而非WM_DESTROY訊息,因為WM_CLOSE訊息
先於後者.

另外,考查以下程式碼:
void CThreadList::UpdateThread(int id,CString client,CString msg)
{
EnterCriticalSection(&CThreadList::csUpDateThread);
{
int ItemCount=m_ListCtrl.GetItemCount() ; //ListCtrl
最多65535條記錄
if(id>ItemCount)
{
for(int i=0;i{
LV_ITEM lvi;

lvi.mask = LVIF_TEXT | LVIF_IMAGE
/* |LVIF_STATE */;
lvi.iItem = ItemCount+i;
lvi.iSubItem = 0;
m_ListCtrl.InsertItem(&lvi);
//m_ListCtrl.SetItemCount(id);
}
}

m_ListCtrl.SetItemText(id-1,0,ito10a(id));
m_ListCtrl.SetItemText(id-1,1,client);
m_ListCtrl.SetItemText(id-1,2,msg);
}
LeaveCriticalSection(&CThreadList::csUpDateThread);
}
這就是執行緒用來的介面函式,該介面CThreadList
是個ListCtrl類,該成員函式的引數中,id,client,msg是介面顯示的內容
函式首先判斷id是否超出現在已經存在的個數,如果超出則增加一到多條記錄
這種動態調整記錄個數的機制比較誘人,但是如果這個函式是在這樣的情況下
被呼叫: frame視窗接受到了WM_CLOSE訊息,在處理訊息之前,首先消滅執行緒
而就在消滅執行緒的過程中,一個未來及消滅的執行緒呼叫了這個函式,該函式在
執行過程中需要執行GetItemCount()函式,跟蹤GetItemCount函式,發現它是
依靠執行SendMessage獲得ItemCount的(SendMessage函式是個不等到結果不
返回的函式),這時會發生的是當機,因為在處理WM_ClOSE訊息
未完成時,又被要求處理SendMessage函式,於是SendMessage函式和WM_CLOSE
訊息處理過程發生了互相等待的事故.
結論是不要線上程向介面報告狀態的過程中呼叫任何依靠訊息工作的函式.
經過考查,幾乎所有介面的函式如SetItemText都是依靠SendMessage
來工作的,所以會到問題的最初:"在多執行緒的程式中,如果執行緒要向介面視窗
報告狀態,有兩種操作方法"在這兩種方法中,第二種方法是行不通的.
※ 來源:·BBS 水木清華站 bbs.tsinghua.edu.cn·[FROM: 166.111.60.81]


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-988857/,如需轉載,請註明出處,否則將追究法律責任。

相關文章