在C++就是使用PostMessage和SendMessage
而在C#其實有另一種委派(delegate),這方面我就不熟了
所以我這邊只講PostMessage和SendMessage
基本上現代的程式都是多執行緒程式,一般在做處理時,要將運算比較多的部分移到背景執行緒去做,最後再通知主執行緒處理畫面UI的動作,這時候就會用到PostMessage和SendMessage,
當然您也可以用Timer監控一些flag做一些UI更新,但是您想想,假設我30ms觸發Timer檢查一次UI要不要更新,那1秒鐘要檢查30次,要是您要檢查很多總類的UI更新,那不就要判斷很多flag例如下面這樣
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
If(flag1)
{
// 更新某部分UI
}
If(flag2)
{
// 更新某部分UI
}
If(flag3)
{
// 更新某部分UI
}
}
這樣有壞處,就是您Timer要一直跑,再來就是您處理這麼多flag更新畫面不累嗎
因此後來就有所謂的PostMessage和SendMessage,通知主Form的WndProc處理畫面
如連結講得的
PostMessage通知完主Form處理會馬上return,當主畫面有空時會去處理接收到的消息(PostMessage一次,會處理一次)
SendMessage則是會Block住,等到送出去的消息處理完,才會執行下一行
基本上意思就是thread做工作,要處理UI時再通知主Form處理,只需要一次的動作,也比較直觀,並且不需要寫一大堆flag做同步動作
當然了thread的處理會有同步的問題要解決,基本上要先知道Critical Section或mutex來處理同步問題,礙於篇幅,這裡先不講,往後會再補充詳細
總之意思大概就是假設您將影像存在一個陣列裡,要是這時您通知主Form處理將影像陣列畫到畫面上,結果您的執行緒在while loop裡又重新將影像陣列重新new,這時您可能剛好再畫影像,結果影像陣列剛好重新new時位置換地方了,導致出錯
這種細節很討厭的,要做很多同步處理,只要沒處理好就會當機,程式根本就不能用
好啦,總之會有同步問題往後有機會會講清楚
這裡您可以參考我的範例裡面註解的地方做建置,您大概就知道用法了,
總之我會有幾個Button,您點點看,照我說的地方下中斷點,追Code看看,您就知道了
這裡就不打那麼多了,請看我的範例就好
總之Wndproc是Windows程式用來接收訊息的地方,每個元件都有一個Wndproc,但是基於方便,我們統一送給主Form的Wndproc,而不是到處送給底下的vcl元件,避免太亂
用法舉PostMessage的例子(SendMessage一樣,只是效果不同)
PostMessage(Handle, WM_EVENT, event, (DWORD)data);
其中Handle是您要處理的主Form
WM_EVENT是自訂義的東西,用來識別您要接收的事件
#define WM_EVENT WM_USER + 10000
Event就是您的事件放在lparam,data,放您要送的變數或指標放在rparam,用以傳遞訊息
總之送過去,您只要照我這樣寫,對應的處理函式會被觸發,您就可以在那邊處理UI的東西了
我這只提供MESSAGE_MAP法,其實您可以virtual繼承Wndproc來觸發您要執行的事件,意思是相同的
這裡要提到的是,照理講,我裡面Button7在執行緒執行UI操作,應該會當掉的,不知道為什麼在XE10沒當…
其實在執行緒執行UI不是每次都會當的,他是有機會當掉,例如兩個執行緒同時存取相同VCL元件,
我範例裡面有6個按鈕5~10,您如果隨便點不點7,10,影像顯示正常,
要是您隨便點的話,例如7,9快速點(先把我連續post_event註解打開,讓他比較容易打架,不然您改成兩個執行緒,用while loop一直畫),過一陣子TImage顯示會異常,
也就是兩個執行緒不能同步更新TImage的,還是乖乖通知主Form更新吧
範例連結
https://drive.google.com/open?id=0B6u5oifJv3EKV184Smh3SFdYelU
沒有留言:
張貼留言