ab.com コミュニティ

ActiveBasicを通したコミュニケーション
現在時刻 - 2024年4月28日(日) 11:17

全ての表示時間は UTC+09:00 です




新しいトピックを投稿する  トピックへ返信する  [ 8 件の記事 ] 
作成者 メッセージ
投稿記事Posted: 2008年3月27日(木) 02:35 
オフライン

登録日時: 2006年6月02日(金) 18:20
記事: 106
一つのスレッドと、ウインドウ上に一つのメニュー「Test」を持つプログラムがあるとします。
ここでウインドウ上のメニュー「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)が
ポストされているなら、それらを全て削除する、というようなことが出来ればと
思っています。

 メッセージキュー中の、同一のメッセージのクリア、について良い方法があれば、
あるいはそれ以外でも、このような連続的なメッセージ・ポストの解消方法があれば
是非教えて下さい。


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2008年3月27日(木) 02:44 
オフライン

登録日時: 2005年7月25日(月) 13:27
記事: 893
お住まい: 埼玉県東松山市
PeekMessage関数を使っているのですから、
補助用の変数を使用して、受け取れなくなるまで受け取り、
最後に取得した有効な物を使用してはどうでしょうか?
#小休止なし無限ループで使う時はGetMessageの方がいい気がします。

あるいは、別途受け取り専用のスレッドを作成し、
その中で専用のキューを用いて処理してもいいかもしれません。

イメージ
作業スレッド→(終了を意味するメッセージを発行)→受け取り用スレッド
↓↑(状態遷移)
受け取り用スレッド→(次のコマンド発行)→作業スレッド
↑(コマンド発行)
Main

又は、今回の場合はメニューを一時的にEnableMenuItem等で押せない状態にするのもいいかもしれません。

_________________
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。


通報する
ページトップ
投稿記事Posted: 2008年3月27日(木) 03:01 
オフライン

登録日時: 2006年6月02日(金) 18:20
記事: 106
konisiさん、レスありがとうございます。
引用:
PeekMessage関数を使っているのですから、
補助用の変数を使用して、受け取れなくなるまで受け取り、
最後に取得した有効な物を使用してはどうでしょうか?
そうなんです。まさにキユーの中から「最後に取得した有効な物」を
取ることが出来ればそもそもクリアなどの必要も無く一番良いのですが、
その方法が分からず、
 ただ単にPeekMessageでは時間的に一番先にポストされたものから
順に取っていってしまうので、、

 もし宜しければその方法を教えていただけたら有り難いです。

(上の仮プロジェクトではPeekMessageである意味はあまり無いのですが
元々のプログラムでスレッド1のループでキー入力などを受け付ているので
GetMessageでなくPeekの方を使わせて貰いました。)


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2008年3月27日(木) 03:41 
オフライン

登録日時: 2005年7月25日(月) 13:27
記事: 893
お住まい: 埼玉県東松山市
だいたいこんな感じですかね?
コード:
Dim myMsg As MSG
Dim myMsg_ As MSG
Do
    If PeekMessage(myMsg_,NULL,0,0,PM_REMOVE)=FALSE then
        Exit Do'メッセージがうまく取得できなくなった
    End If
    'ここら辺でmyMsg_の情報を解析して、コピーする必要が無ければそのままcontinueしてもいいと思う。

    myMsg=myMsg_'本体に情報をコピー
Loop'抜けた時にmyMsgに最終情報が入っている。ただしキューは空になってしまう。
この手の奴はあまりやったことがないので正しいかどうか自信がないのですが。

追記:今思いついたのですが、同じような手法で作業終了時にキューを空にしてあげるというのもいいかもしれません。

_________________
Website→http://web1.nazca.co.jp/himajinn13sei/top.html
ここ以外の場所では「暇人13世」というHNを主として使用。

に署名を書き換えて欲しいと言われたので暇だしやってみるテスト。


通報する
ページトップ
投稿記事Posted: 2008年3月27日(木) 04:34 
オフライン

登録日時: 2006年6月02日(金) 18:20
記事: 106
引用:
'ここら辺でmyMsg_の情報を解析して、コピーする必要が無ければそのままcontinueしてもいいと思う。
僕の理解がいまいちあやふやで申し訳ないのですが
「myMsg_」はメッセージ構造体でこれは「メッセージ・キュー」では
無いですよね。つまりこの中にはポストされたメッセージ自体に関する
情報が入っている。
このメッセージが時間的にもっとも後にポストされたものかどうかを
知るには、「メッセージ・キュー」全体を見ることが
必要なのではないでしょうか。

「キューを空に」というのも出来たら良いのですが、どうやってキューに
アクセスしたらいいのか。。
Googleなどで少し調べたりもしているんですけども、それが悩んでいる所です。


通報する
ページトップ
 記事の件名: Do~Loop?
投稿記事Posted: 2008年3月27日(木) 06:16 
オフライン

登録日時: 2006年6月02日(金) 18:20
記事: 106
書いて頂いたプログラムは「Do~Loop」でメッセージを取れるだけ取って
その結果メッセージキュー全体を取り出す、という理解で良いでしょうか?
だとしたら僕の上の
引用:
このメッセージが時間的にもっとも後にポストされたものかどうかを
知るには、「メッセージ・キュー」全体を見ることが
必要なのではないでしょうか。
というのは、これによって実現されていますね。浅い理解ですみません。

ただこの方法は、もしメッセージキュー中に他の別のメッセージがまぎれて
ポストされていた場合、最後のMYTHREADMSG_TESTの検出の為に
キューの取り出し先頭位置を繰り上げ続けてしまい、結果
本来のメッセージ取得ループおいて、その別のメッセージを取り逃がすことも
あるのではないかとも思いますが、、
 どうでしょうか?


通報する
ページトップ
 記事の件名:
投稿記事Posted: 2008年3月27日(木) 13:34 
オフライン

登録日時: 2005年5月31日(火) 17:59
記事: 899
お住まい: 東京都
それならPeekMessage(myMsg_, NULL, MYTHREADMSG_TEST, MYTHREADMSG_TEST, PM_REMOVE)とすればよいです。
PeekMessageとGetMessageは,3番目の引数から4番目の引数までの範囲のメッセージだけを対象にするという使い方ができます。
(普段よくやる両方に0を指定した場合は、全てのメッセージが対象になります)


通報する
ページトップ
投稿記事Posted: 2008年3月27日(木) 23:38 
オフライン

登録日時: 2006年6月02日(金) 18:20
記事: 106
引用:
それならPeekMessage(myMsg_, NULL, MYTHREADMSG_TEST, MYTHREADMSG_TEST, PM_REMOVE)とすればよいです。
PeekMessageとGetMessageは,3番目の引数から4番目の引数までの範囲のメッセージだけを対象にするという使い方ができます。
peekMessageのヘルプを見たとき、これらの設定は何の為にあるんだろうと
思っていたところです。
これに先のDo~Loopチェックを組み合わせればキューの中から
MYTHREADMSG_TESTだけを削除することが可能ですね。
ありがとうございます。

それからkonisiさんが指摘されていたように「処理」の実行中
メニュークリックを無効化ロックしてそもそもメッセージを溜めないようにすることも
安全な処置だなと思っています。

konisiさん、イグトランスさん、レスありがとうございました。


通報する
ページトップ
期間内表示:  ソート  
新しいトピックを投稿する  トピックへ返信する  [ 8 件の記事 ] 

全ての表示時間は UTC+09:00 です


オンラインデータ

このフォーラムを閲覧中のユーザー: なし & ゲスト[6人]


トピック投稿:  可
返信投稿:  可
記事編集: 不可
記事削除: 不可
ファイル添付: 不可

検索:
ページ移動:  
Powered by phpBB® Forum Software © phpBB Limited
Japanese translation principally by ocean