6.27.2007

UpdateData in Thread

在Thread 中call UpdateData( )會導致Crash。
據說,Win32 programming 有一條Rule(http://forums.ni.com/ni/board/message?board.id=231&message.id=4331):
"Thou shall not access UI controls from a thread other than the one that created the UI control in the first place"
因為Dialog 不是Thread Safe。
所以,可以用UpdateData( )這個funciton 的,也只有Dialog 自己這個thread 囉。

那Dialog create 出來的Thread 要怎麼update dialog 的data呢?

一般的解法是用Message,Thread Post Message,叫Dialog UpdateData。
例如在 這一篇 (http://forums.microsoft.com/msdn/showpost.aspx?postid=95099&siteid=1)所列出的code :
#define WM_USER_UPDATE_DATA      ( WM_USER + 1 )

void UpdateUserData( BOOL bUpdate )
{
SendMessage( WM_USER_UPDATE_DATA, bUpdate, 0 );
}

LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if( message == WM_USER_UPDATE_DATA ) {
if( wParam )
UpdateData( TRUE );
else
UpdateData( FALSE );
}
}
然後其他的Thread 都呼叫UpdateUserData( )來代替 UpdateData( )。

看起來似乎OK,但是在CE這種,OEM到處定義WM_USER+XX 的系統,要找到一個safe 的 message number 還真不容易呀,稍不小心就會誤觸地雷。

Robert 說WM_USER+XX 的scope只在同一個AP。所以不用擔心會有和其他AP重複定義的問題。

另外Robert說在Thread中和Dialog要互通資料,一般會用Timer Trigger,比較安全,然後其中用queue來傳遞資料。

  • 所以如果說是經常update的資料,就用Timer。
  • 如果是偶而才 update一次,就用 WM_USER+XX。
總整理:
  • 在Dialog 本身的Thread中,用UpdateData
  • 在其他的Thread中,用PostMessage( )通知Dialog作UpdateData( )。
所以Dialog Create 的Thread在使用Dialog 本身的funciton 時,要注意那個Function 有沒有呼叫UpdateData( ),否則會發生其他人使用沒事,但是Thread用有事的情況。

不然就要一勞永逸,大家都用PostMessage,由Dialog的WinProc 統一UpdateData( )。


關於Thread中呼叫UpdateData( )來Update UI 內容,這一篇(http://blog.csdn.net/jeven2005/archive/2007/02/14/1510039.aspx)也有詳細的說明:解法也是使用USER MESSAGE。

關於這一點還真有名呀,另外類似的rule有:
這一篇(http://www.codeproject.com/cpp/
avoidupdatedata.asp?df=100&forumid=696&exp=0&select=845137
)的
DO NOT EVER TOUCH A WINDOW FROM A THREAD.

沒有留言: