メインウインドウのクリエイト部でCreateThreadにより宣言、開始された
一つのスレッドを持つプログラムがあるとします。
メイン・ウインドウが非アクティブになった時に
そのスレッドを停止させ、またアクティブになった時に再開させたい
と思い下のようにプログラムを書きました。
メイン・ウインドウのアクティベイト・イベントでスレッドに対して
スレッド停止・再開のメッセージを送り、
それをスレッドで拾って自らを停止・再開させます。
コード: 全て選択
'
'●ウインドウ・アクティブ/非アクティブ・イベント
'
Sub MainWnd_Activate(state As Integer, minimized As Integer)
If state=WA_INACTIVE Then
PostThreadMessage(hMainWnd, MYTHREADMSG_IDLE_THREAD, 0, 0)
Print "スレッド停止"
Else
PostThreadMessage(hMainWnd, MYTHREADMSG_RESUME_THREAD, 0, 0)
Print "スレッド再開"
End If
End Sub
として、そのポストされたメッセージをスレッド内で拾うために、
コード: 全て選択
While 1 'スレッドのループ用
ret=PeekMessage(msg,0,0,0,PM_REMOVE)
If ret=TRUE Then
Select Case msg.message
Case MYTHREADMSG_IDLE_THREAD
'----- スレッド停止ループ -----
' RESUME_THREADメッセージを受け取るまでここで待機ループ。
While msg.message<>MYTHREADMSG_RESUME_THREAD
ret=GetMessage(msg,0,0,0)
If ret=-1 Or ret=0 Then Exit Function
Wend
'----- スレッド停止ループ・終わり -----
このようにプログラムを書きました。
ただし実行してみたのですがこの方法ではうまく行きません。
まず第一にスレッド内で、ポストされているはずのMYTHREADMSG_IDLE_THREADを
拾ってくれない。
次に、五回に一度くらいの頻度で
ABのエラーでは無いWindowsのシステムのエラー表示で
「test.debugが原因でKRNL386.EXEにエラーが発生しました。
問題が解決しない場合はコンピュータを再起動してください。」
というようなダイアログが出て止まります。
元々はスレッドの停止、再開にActivateイベントで
「SuspendThread」、「ResumeThread」命令を使っていたのですが
これだとスレッド処理中のどこの時点で止められるのがか分からないので、
("強制的に停止・再開させる"という記述も見られますが)
(例えば画面を半分描画したところで中途半端に止められてしまったり)
それを防ぐ為に、上のように"スレッドにメッセージをポストして、
それをスレッド側で拾って自らを停止させる"という形で作ったのですが、
これではどうもダメなようです。
メッセージのポストを拾ってくれないなら、停止フラグとしてグローバル変数を
一つ用意してその値をActivateイベントでセット・リセットして、スレッド内でその
変数を参照して、、とも思ったのですが、異なるスレッドで同じ変数を共用する
というのもどうにも危なっかしいような気もして、躊躇しています。
そもそもなぜメッセージを拾ってくれないのか、その原因が分からないままで
小手先を変えただけの方法を使うのも何だか不気味です。
スレッド処理の一連の流れを妨げないように停止位置をコントロールしつつ、
スレッドを停止・再開させる方法がありましたら教えてください。