by jacoby » 2008年3月27日(木) 02:35
一つのスレッドと、ウインドウ上に一つのメニュー「Test」を持つプログラムがあるとします。
(ここにプログラムが表示されます。プロジェクトファイル AB4.24) [ここをクリックすると内容が表示されます] [ここをクリックすると非表示にします]
コード: 全て選択
'-----------------------------------------------------------------------------
' イベント プロシージャ
'-----------------------------------------------------------------------------
' このファイルには、ウィンドウ [MainWnd] に関するイベントをコーディングします。
' ウィンドウ ハンドル: hMainWnd
#prompt
' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。
Const MYTHREADMSG_TEST=1000
' スレッド1のハンドル
Dim hThread1 As HANDLE
Dim thread1_ID As DWord
'-----------------------------------------------------------------------------
' ウィンドウメッセージを処理するためのコールバック関数
Function MainWndProc(hWnd As HWND, dwMsg As DWord, wParam As WPARAM, lParam As LPARAM) As DWord
' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。
' イベントプロシージャの呼び出しを行います。
MainWndProc=EventCall_MainWnd(hWnd,dwMsg,wParam,lParam)
End Function
'-----------------------------------------------------------------------------
' ここから下は、イベントプロシージャを記述するための領域になります。
'
'●デストロイ
'
Sub MainWnd_Destroy()
ThreadMessageTest_DestroyObjects()
PostQuitMessage(0)
End Sub
'
'●クリエイト
'
Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT)
' スレッドの定義
hThread1=CreateThread(ByVal 0,0,AddressOf(MainOperation),0,0,VarPtr(thread1_ID))
End Sub
'
'●Testメニュー・クリックイベント
'
Sub MainWnd_IDM_Test_MenuClick()
PostThreadMessage(thread1_ID,MYTHREADMSG_TEST,0,0)
End Sub
'
'●スレッド1
'
Function MainOperation(dwDummy As DWord) As DWord
Dim ret As Long
Dim myMsg As MSG
While 1
ret=PeekMessage(myMsg,NULL,0,0,PM_REMOVE)
If myMsg.message=MYTHREADMSG_TEST Then
Print "Got MYTHREADMSG_TEST"
Sleep (3000)
End If
Wend
End Function
ここでウインドウ上のメニュー「Test」をクリックすると
スレッド内の特定の処理を行わせたいとします。
メニュー「Test」クリック・イベントで
コード: 全て選択
'
'●Testメニュー・クリックイベント
'
Sub MainWnd_IDM_Test_MenuClick()
PostThreadMessage(thread1_ID,MYTHREADMSG_TEST,0,0)
End Sub
スレッド1にPostThreadMassageにより"MYTHREADMSG_TEST"をポスト
これをスレッド1中の
コード: 全て選択
ret=PeekMessage(myMsg,NULL,0,0,PM_REMOVE)
で拾い、
コード: 全て選択
If myMsg.message=MYTHREADMSG_TEST Then
Print "Got MYTHREADMSG_TEST"
Sleep (3000)
End If
として、If文の中でとりあえず仮の処理(3秒待つ)を行わせています。
ここで問題なのが、その特定の「処理」がかなり時間の掛かるものだった
場合、メニュー「Test」をせわしなく連続的にクリックした時にメッセージキューの
中に信号メッセージであるMYTHREADMSG_TESTが一方的に溜まっていってしまい
それらのメッセージがすべて無くなるまで「処理」を実行し続けてしまいます。
もちろんこのこと自体は正常な動作なのですが、仮に、スレッド1内の
PeekMassageでMYTHREADMSG_TESTを受け取ったとき、
メッセージキュー中に他にも同一のメッセージ(MYTHREADMSG_TEST)が
ポストされているなら、それらを全て削除する、というようなことが出来ればと
思っています。
メッセージキュー中の、同一のメッセージのクリア、について良い方法があれば、
あるいはそれ以外でも、このような連続的なメッセージ・ポストの解消方法があれば
是非教えて下さい。
一つのスレッドと、ウインドウ上に一つのメニュー「Test」を持つプログラムがあるとします。
[hide=(ここにプログラムが表示されます。プロジェクトファイル AB4.24)]
[code]
'-----------------------------------------------------------------------------
' イベント プロシージャ
'-----------------------------------------------------------------------------
' このファイルには、ウィンドウ [MainWnd] に関するイベントをコーディングします。
' ウィンドウ ハンドル: hMainWnd
#prompt
' TODO: この位置にグローバルな変数、構造体、定数、関数を定義します。
Const MYTHREADMSG_TEST=1000
' スレッド1のハンドル
Dim hThread1 As HANDLE
Dim thread1_ID As DWord
'-----------------------------------------------------------------------------
' ウィンドウメッセージを処理するためのコールバック関数
Function MainWndProc(hWnd As HWND, dwMsg As DWord, wParam As WPARAM, lParam As LPARAM) As DWord
' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。
' イベントプロシージャの呼び出しを行います。
MainWndProc=EventCall_MainWnd(hWnd,dwMsg,wParam,lParam)
End Function
'-----------------------------------------------------------------------------
' ここから下は、イベントプロシージャを記述するための領域になります。
'
'●デストロイ
'
Sub MainWnd_Destroy()
ThreadMessageTest_DestroyObjects()
PostQuitMessage(0)
End Sub
'
'●クリエイト
'
Sub MainWnd_Create(ByRef CreateStruct As CREATESTRUCT)
' スレッドの定義
hThread1=CreateThread(ByVal 0,0,AddressOf(MainOperation),0,0,VarPtr(thread1_ID))
End Sub
'
'●Testメニュー・クリックイベント
'
Sub MainWnd_IDM_Test_MenuClick()
PostThreadMessage(thread1_ID,MYTHREADMSG_TEST,0,0)
End Sub
'
'●スレッド1
'
Function MainOperation(dwDummy As DWord) As DWord
Dim ret As Long
Dim myMsg As MSG
While 1
ret=PeekMessage(myMsg,NULL,0,0,PM_REMOVE)
If myMsg.message=MYTHREADMSG_TEST Then
Print "Got MYTHREADMSG_TEST"
Sleep (3000)
End If
Wend
End Function
[/code]
[/hide]
ここでウインドウ上のメニュー「Test」をクリックすると
スレッド内の特定の処理を行わせたいとします。
メニュー「Test」クリック・イベントで
[code]
'
'●Testメニュー・クリックイベント
'
Sub MainWnd_IDM_Test_MenuClick()
PostThreadMessage(thread1_ID,MYTHREADMSG_TEST,0,0)
End Sub
[/code]
スレッド1にPostThreadMassageにより"MYTHREADMSG_TEST"をポスト
これをスレッド1中の
[code]
ret=PeekMessage(myMsg,NULL,0,0,PM_REMOVE)
[/code]
で拾い、
[code]
If myMsg.message=MYTHREADMSG_TEST Then
Print "Got MYTHREADMSG_TEST"
Sleep (3000)
End If
[/code]
として、If文の中でとりあえず仮の処理(3秒待つ)を行わせています。
ここで問題なのが、その特定の「処理」がかなり時間の掛かるものだった
場合、メニュー「Test」をせわしなく連続的にクリックした時にメッセージキューの
中に信号メッセージであるMYTHREADMSG_TESTが一方的に溜まっていってしまい
それらのメッセージがすべて無くなるまで「処理」を実行し続けてしまいます。
もちろんこのこと自体は正常な動作なのですが、仮に、スレッド1内の
PeekMassageでMYTHREADMSG_TESTを受け取ったとき、
メッセージキュー中に他にも同一のメッセージ(MYTHREADMSG_TEST)が
ポストされているなら、それらを全て削除する、というようなことが出来ればと
思っています。
メッセージキュー中の、同一のメッセージのクリア、について良い方法があれば、
あるいはそれ以外でも、このような連続的なメッセージ・ポストの解消方法があれば
是非教えて下さい。