PostThreadMessageとPeekMessageについて

解決


たばた  2007-06-23 02:32:33  No: 65447

お世話になります。VC6でMFC使ってます。
GUIから、ワーカースレッドに対してメッセージを
投げたいと思ってます。ソースの要所のみ書きます。

<<GUIスレッド側>>
1.ワーカスレッド生成時
ThreadHandle = _beginthreadex(NULL, 0, AAAAAA, (void*)&Param,
                                0,&ThreadID);
2.停止メッセージ&停止時のルーチン
#define WM_THREADSTOP (WM_APP + 200)
int n = PostThreadMessage(ThreadID, WM_THREADSTOP, 0, 0);

3.ワーカスレッド関数
unsigned int WINAPI AAAAAA(void *pParam)
{
  BOOL bEndFlg = FALSE;

  while(1)
  {
    // メッセージ処理
☆1    if (PeekMessage(&Msg, (HWND)-1, 0, 0, PM_REMOVE) != 0)
☆2    if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE) != 0)
    {
      switch(Msg.message)
      {
        case WM_THREADSTOP:  // スレッド停止メッセージ
          // 終了フラグセット
          bEndFlg = TRUE;
          break;
        default:
          break;
        }
      }
      // スレッド終了判定
      if (bEndFlg) break;
  
      Sleep(300);
  }
  _endthreadex(0);
  return (0);
}

メインの処理部分は割愛しましたが、見ての通りで自作
メッセージ(WM_THREADSTOP)をトリガにして、スレッドの
停止をしたいと思ってます。
2.のPostThreadMessage()の戻り値は「1」でメッセージ
そのものは投げられているようなのですが、3で受け取る事が
出来ません。★部分のPeekMessage()に関して、MSDNを参照
すると・・・
----------------------------------------------------
以下MSDN引用
hWndパラメータでNULLを指定した場合、PeekMessage 関数を
呼び出した現在のスレッドに所属する任意のウィンドウに関連
付けられているメッセージを取得します(PeekMessage 関数は、
ほかのスレッドに所属するウィンドウに関連付けられているメッ
セージは取得しません)。(☆.1)

hWnd パラメータで-1を指定すると、PeekMessage 関数は、
PostThreadMessage 関数がポストした、hWnd パラメータで
NULLを指定しているメッセージを取得します。(☆.2)
----------------------------------------------------
どちらのパターンも試したのですが無理でした。又、

----------------------------------------------------
PeekMessage は必ず WM_QUIT メッセージを取得することに
注意してください。
----------------------------------------------------
2.でWM_QUITを投げたら届きました・・・。
自前のメッセージが届かないのは何が問題なのでしょうか?
宜しくお願いします。


たばた  2007-06-23 02:59:13  No: 65448

取り合えず試してみたのが、

PeekMessage()をGetMessage()に変えてみたところ、
上手くいきました。。
が、GetMessage()だとメッセージ待ちしてしまうん
ですよね?それが困るのでPeekMessage()なのですが・・・

ブロック/ノンブロック以外に両者の違いって
何でしょうか・・・?


たばた  2007-06-23 03:56:22  No: 65449

なんか一人でバタバタして申し訳ありません。
上のソースなんですが、要所だけをかいつまんで
提示したのですが、実際のソースも上記と同じ様に
最小限の動作で試したところ、PeekMessage()でも
メッセージを取ることが出来ました。
と、言うことは、実際処理が行われてる最中に
メッセージの取りこぼしが起きていると思うの
ですが、どうすれば取りこぼさないように出来るの
でしょうか?
自己解決と質問の繰り返しで申し訳ありません。
どなたか解説頂けませんでしょうか?


yoh2  2007-06-23 07:02:26  No: 65450

この条件に引っかかっていたりしませんか?

PostThreadMessage()の解説:
http://msdn2.microsoft.com/en-us/library/ms644946.aspx
| As a general rule, messages that are not associated with a window
| cannot be dispatched by the DispatchMessage function. Therefore, if
| the recipient thread is in a modal loop (as used by MessageBox or
| DialogBox), the messages will be lost.

また、終了通知を得るだけなら、メッセージを用いる代わりに、イベント + タイムアウトを0にした
WaitForSingleObject()との組合わせを用いるのはいかがでしょうか。


たばた  2007-06-23 18:24:22  No: 65451

私もこの文章は読んだのですがイマイチ理解出来てません。
「スレッド内でMessageBoxやDialogBoxを使うとメッセージ
とりこぼすよ」って解釈で良いのでしょうか?
確かに割愛してる処理部分で判定によりでMessageBoxを出す
ような処理はあるのですが、テストで実行中の場合は出さない
様にしていたので大丈夫かな?とは思っていたのですが。
実際はエラー時等の警告や通知をMessageBoxで行うので、
MesssageBoxが表示されている間はメッセージの取りこぼしは
しょうがないのかな?とは思ってます。

提示例では終了通知だけなんですが、実際は他の通知もいくつか
あるため、この方法しかないのです。
スレッドは何度か使ったことがあるのですが、メッセージのやり
取りは初めてでなかなか難しいです。peekmessageもループ内で
sleep(1)を入れまくってやらないと使用率上がりっぱなしなんで
すが、そういうものなんでしょうか?

以上宜しくお願いします。


Ban  2007-06-23 20:53:13  No: 65452

> 提示例では終了通知だけなんですが、実際は他の通知もいくつか
> あるため、この方法しかないのです。

通知内容別に複数のイベントを作って、WaitForMultipleObjectsを使えばいいだけでは?
何スレッド起こすかにもよるでしょうが、リソースがカツカツなんて昨今そうはないでしょうし。

> peekmessageもループ内でsleep(1)を入れまくってやらないと
> 使用率上がりっぱなしなんですが、そういうものなんでしょうか?

ブロックせずにチェックするだけなのですから、
他(Sleep等)で別途、ブロックして制御を手離さなければそういうものです。
# そして、状況によってCPU使用率100%が必ずしも悪いとは限りません。
# まぁ、終了待機の為だけに100%だったらまずいとは思いますが…。

Sleep入れるくらいなら、MsgWaitForMultipleObjectsExとか検討した方がよいのかも。


Ban  2007-06-23 20:54:15  No: 65453

> 通知内容別に複数のイベントを作って、WaitForMultipleObjectsを使えばいいだけでは?

# 通知をキューイングしておくケースとかあると向いてませんが。


瀬戸っぷ  2007-06-23 20:59:07  No: 65454

> 提示例では終了通知だけなんですが、実際は他の通知もいくつか
> あるため、この方法しかないのです。

数と受け渡しするもの(シグナルだけでよいのか/付加情報があるか)にもよりますが、
WaitForMultipleObjects()で対処するという方法もアリかと。
# 私の自作メールチェッカーではユーザ中断とソケットのタイムアウト、ソケット受信をWaitForMultipleObjectsで監視させています。
## スレッドごとのメッセージキューとかやったことないだけですけど(^_^;)


たばた  2007-06-23 21:17:08  No: 65455

お返事ありがとうございます。

>通知内容別に複数のイベントを作って、WaitForMultipleObjectsを使えばいいだけでは?
>何スレッド起こすかにもよるでしょうが、リソースがカツカツなんて昨今そうはないでしょうし。

このイベントと言うのが理解出来てません。ウィンドウズのメッセージの
様に飛ばせると言う認識で良いのでしょうか?
どんな風に使えるのか簡単で良いのでそのあたりご説明頂けませんか?

このスレッドでやりたい事は、あるフォルダ内のファイルのチェックを
行い、そのファイルの種別や内容の一部をGUIに表示させたいと考えてます。
GUI上では、監視するフォルダやその他チェック内容のoption等の変更が
可能であり、変更された場合はスレッドにメッセージを飛ばして、監視
フォルダの変更などをさせたいと思ってます。
それと終了通知です。(上にいくつかと書きましたが現状は2つだけですね。)

ちなみに、書き忘れてましたがMFCを使ってます。今回の件を色々と調べてる
うちに_beginthreadex()は使っちゃマズい様な記述を見受けました。
AfxBeginThread()にしないと動作が怪しくなるような話もありましたが、
今回のメッセージ云々にも絡んでくる問題だったりしますか?
MFCもC関数も両方使うのですが・・・。(この件に関しては別スレのが良いかな?)

なんか質問責めになっちゃってますが、主題はメッセージのやり取りで
上記の様な使い方をしたい場合にセオリー的なものを教えて頂ければ
嬉しいです。宜しくお願い致します。


Ban  2007-06-24 01:28:43  No: 65456

CreateEventというAPIがあります。同期オブジェクトの一種で、いわゆるフラグです。

MFCのクラスを使う場合には、AfxBeginThreadである必要がありますね。
直接は関係ないかもしれませんが、MFCのオブジェクトを内部で使っていて、
_beginthreadexなのだとすれば、それは仕様を満たしていないバグでしょう。

セオリーという意味では、(状況にもよりますが)Eventはセオリーの一つです。
スレッド内部が例えばGUIなどのために、メッセージループ(GetMessageやPeekMessage)を必要としているならば、メッセージの方が向いていることも多いですが、
ワーカスレッドの終了通知という意味では、唯のグローバルか、
Event通知か、というのが双璧ではないでしょうか。


たばた  2007-06-24 02:28:13  No: 65457

順番が変わってしまいますが・・・。

>MFCのクラスを使う場合には、AfxBeginThreadである必要がありますね。
よくよく考えてたら、スレッドの中でMFCと言ったらCString程度しか
使ってない事に気が付きました・・・。stringクラスにしてしまえば
_beginthread(ex)でも良いんですよね?
とは言ってももうAfx〜()にしてしまったのでそのまま行くつもりですが。

>CreateEventというAPIがあります。同期オブジェクトの一種で、いわゆるフラグです。
これで、終了通知とオプションの変更通知のフラグを作って、
GUIスレッドの方でフラグをONしてやって、ワーカースレッドで
参照してOFFにするって感じでしょうか?調べてみます。

>スレッド内部が例えばGUIなどのために、メッセージループ(GetMessageやPeekMessage)を必要としているならば
例えばワーカースレッドでプログレスバーを表示したりする場合で
の処理状況をGUIスレッドから処理状況を受け取る必要がある場合
なんてのが該当する例でしょうか?
そうなると私の場合は基本的にフラグとしての通知するだけだから
あまりメッセージを使うメリットはないんですね。

>唯のグローバルか、
これが一番早くて楽ですね・・・あまり使いたくはありませんが。
回答有難う御座いました。
イベントを使う方法も考慮してもうちょっと頑張ってみます。

で、話が本題とちょっとズレてしまって、結局ズバリの回答が無い
のですが、結局「メッセージの取りこぼし」と言うのは普通にある
のでしょうか?

  for (int i = 0; i < 100; i++){
    RecvThreadHandle->PostThreadMessage(WM_CHGSET, 0, 0);
  }
  DWORD Val = GetQueueStatus(QS_POSTMESSAGE);
  TRACE("GetQueueStatus:[0x%08x]\n", Val);

この書き込みをするまでの間色々とやってみました。
上記のルーチンは、100回設定変更のメッセージを投げつけ、
GetQueueStatus()でキュー内のメッセージの個数(?)を表示させてる
(つもり)なんですが、このソースをボタンAとボタンBで実行させると
GetQueueStatus()の結果が違うのです。片方は0x00080008で片方は0です。

このルーチンでは100回連発してますが、スレッド側では1回しか受けつけません。
(スレッド側ではpeekmessageが受信した所でTRACE()で表示させてます。)
また単発で送信する様にした場合でも、押した回数だけ反応したりしなかったりです。

環境はWin2Kですが、MSDNを見るとメッセージ数の上限は10000個の様なので、
100回ぐらいじゃ屁でもないと思うのですが。自分で送りつけてるもの以外にも
OSやGUIから何らかのメッセージがバンバン来てるってのもあるのでしょうか?
そう思ってPeekMessage()のフィルタ引数も「自分メッセージの範囲だけ」に
設定してみたりもしたのですが。。

イベントで処理をする事により上手く行くのは良いのですが、やり始めて腑に
落ちずにやり方を変えるのも気分が悪いので、もしどなたか回答&お付き合い
頂ける方おりましたらレス下さい。
長文申し訳ありません。宜しくお願い致します。


Ban  2007-06-24 04:49:35  No: 65458

普通は、積んだことが確認できれば(フィルタリングされることはあっても)
取りこぼしたりしないと思いますので、何かが起きてるのは確かかと。

で、GetQueueStatusの戻りは、メッセージの個数ではないですよ?
メッセージの型(詳細はMSDN参照)が返るだけなので、
0x00080008だとQS_POSTMESSAGE、PostMessageは有効だったようですね。
# そして、GetQueueStatusの結果は、PeekMessageが実行されたり、
# 他のシステムメッセージが発生したりでも変わってしまいます。あまり当てになりません。


Ban  2007-06-24 04:51:54  No: 65459

ボタンAとかBってのはなんでしょうか?
GetQueueStatusは「自スレッド」の結果を返すと思いますが、
上記の呼び出しコンテキストはどこですか?
PostThreadMessageをしているスレッドと、キューがあるスレッドは同一
(自分へのPost)で試された結果でしょうか?


Ban  2007-06-24 05:08:07  No: 65460

# 分割/連投申し訳ありません。

> そう思ってPeekMessage()のフィルタ引数も「自分メッセージの範囲だけ」に

PeekMessageのフィルタリングを設定しようがしまいが、
Post時点で既にキューに積まれていることは変わりないので、
もしも本当にあふれているのだとしても何の改善/解決にもなりませんが…。

PeekをNOREMOVEかつメッセージ指定なしにしたらどうなりますか?
(必要ならGetMessageでRemoveする)

ちなみに、スレッド側の回数はどうやって数えているので?
受信したところというのは、PeekMessageが0以外を返したところですか?

# どうも、取りこぼしているというより、予期せぬメッセージがキューに入って、
# それがスタックしてるような気が…。


  2007-06-24 05:22:28  No: 65461

<MSDN>
GetMessage:
The function dispatches incoming sent messages
until a posted message is available for retrieval. 
PeekMessage:
The PeekMessage function dispatches incoming sent messages,
checks the thread message queue for a posted message, and retrieves the message (if any exist).
</MSDN>
Win32はpostとsendを区別しますが、
いずれも処理優先度は以下のとおりなので、
1.Sent messages 
2.Posted messages 
(以下略)
何らかのSendがスレッドに対して行われたりしてるとそれをdispatchする必要があったりとか。


たばた  2007-06-24 10:10:49  No: 65462

お返事遅くなりました。
(しかも一生懸命書いたのにESCキーでパーorz。)

>で、GetQueueStatusの戻りは、メッセージの個数ではないですよ?
すみません。完全に認識違いのようでしたね・・・。
Postした後でキューの中身を調べて個数を返してくれるものとばかり
思ってました。

>PeekをNOREMOVEかつメッセージ指定なしにしたらどうなりますか?
>(必要ならGetMessageでRemoveする)
やってみましたが変わりませんでした。

>ちなみに、スレッド側の回数はどうやって数えているので?
>受信したところというのは、PeekMessageが0以外を返したところですか?
送信側は2通り試してみました。
1.GUI側で上のソースにある、PostThreadMessage()を100回For分で送信。
2.GUI上にボタンを1つ作成し、staticの値を持たせてボタンを連打した回数。

で、受信側が、書かれている通りで、PeekMessageが0以外の場合はTRACE()で
文字列を表示させています。

>何らかのSendがスレッドに対して行われたりしてるとそれをdispatchする必要があったりとか。
このあたりがさっぱりなのですが、私が作ったワーカースレッドに対して、
私以外の誰かがメッセージを送りつけて来てると言う可能性があると言う
事でしょうか?
ちなみにもし誰かがSendでメッセージを送りつけてるとした場合でも、スレッド
ではPeekMessage()で判定して該当のメッセージ以外は何も処理をしないで、
またPeekMessage()を呼ぶので、なんら問題はないような気がしますが・・・。
SendとPostされたものって扱いに差があるのですか?
送信側がブロックされるかされないかだけの違いだと思っているのですが。

動作から推測するとやはり間違いなく取りこぼしorマージ(?)されていると
しか思えないのですが、マージなんてされた場合はシューティングゲームなんか
で弾の描画をスレッドでやらせてた日には1発しか弾が出ないなんて事になり
ますよね?
こんな事で困っているのは私だけなのでしょうか?
Banさん長々とお付き合いさせてしまって申し訳ありません。


Ban  2007-06-24 10:56:30  No: 65463

> for (int i = 0; i < 100; i++){
>     RecvThreadHandle->PostThreadMessage(WM_CHGSET, 0, 0);
> }
> DWORD Val = GetQueueStatus(QS_POSTMESSAGE);
> TRACE("GetQueueStatus:[0x%08x]\n", Val);

GetQueueStatusをここで呼ぶと、PostThreadMessageを呼んだ方(メイン側?)の
スレッドキューを見ると思いますが。ワーカスレッドの方で呼んでますか?
並んで書いてあるだけで、実はGetQueueStatusの方はちゃんとワーカスレッドにありますか?

Postの100回は全部成功してるのですよね。

> ちなみにもし誰かがSendでメッセージを送りつけてるとした場合でも、
> スレッドではPeekMessage()で判定して該当のメッセージ以外は何も処理をしないで、
> またPeekMessage()を呼ぶので、なんら問題はないような気がしますが・・・。

「該当のメッセージしか処理しない」ってのが、逆に問題なのではないかとの憶測なのですが。

> SendとPostされたものって扱いに差があるのですか?
> 送信側がブロックされるかされないかだけの違いだと思っているのですが。

MSDNの記述は、全部区別してかかれてますよ>SendとPost。
内部処理が違うものですから。

# できれば最小限の再現コードが欲しいですね…。


たばた  2007-06-24 19:45:16  No: 65464

おはようございます。

>実はGetQueueStatusの方はちゃんとワーカスレッドにありますか?
いえ。ひとかたまりでGUIスレッドの方で処理してます。
ワーカースレッド側でやってみるといいかも知れませんね。

>Postの100回は全部成功してるのですよね。
成功してます。

>「該当のメッセージしか処理しない」ってのが
でも、一番最初に提示したソース部分では、
switchで、defaultで何も処理せずに飛ばしてますが・・・
ここでsendとpostの差が出てくるのでしょうか?
実はsendされたものはpeekmessageで取れないとか。。
ってのはないですよね・・・。

午後に出社して作業なもので、その際にもう少し詳細な
ソース提示します。


Ban  2007-06-24 21:30:50  No: 65465

> ワーカースレッド側でやってみるといいかも知れませんね。

いいかもではなくて、そうやらないと何の意味もないはずでは…?
状態が見たいのは、ワーカスレッドのメッセージキューですよね?
<MSDN(強調済)>
The GetQueueStatus function indicates the type of messages found
in the **calling thread's** message queue.
</MSDN>
Postしたスレッドで呼んでも、ワーカスレッドの状態は取れませんよ?


たばた  2007-06-25 00:02:01  No: 65466

>状態が見たいのは、ワーカスレッドのメッセージキューですよね?
すみません。その通りです。
実際にワーカースレッド側でやってみました。
ちなみに

☆GUI側テスト用ボタンイベント
void CxxxDlg::OnBtnDummy() 
{
  // スレッドに変更を通知
  int i,n;
  for (i = 0; i < 100; i++)
  {
    n = RecvThreadHandle->PostThreadMessage(WM_CHGSET, 0, 0);
    
    if (n != 1) TRACE("PostThreadMessage_ERR!!\n");
  }
  
  TRACE("送信完了\n");
}

☆スレッド側
unsigned int xxxxxThread(void *pParam)
{
  〜変数設定等(省略)〜

  // メッセージキュー作成
  PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE);
  ☆初回にコレを呼ぶ事によりMsgキューが作成されると
    MSDNにあったもので。

  DWORD aaa;

  while(1)
  {
    aaa = GetQueueStatus(QS_POSTMESSAGE);
    TRACE("PeekMessage直前/GetQueueStatus():[0x%08x]\n", aaa);

    // メッセージ処理
    nRet = PeekMessage(&Msg, NULL, 0, 0, PM_NOREMOVE);
    
    aaa = GetQueueStatus(QS_POSTMESSAGE);
    TRACE("PeekMessage[nRet=%d]/GetQueueStatus():[0x%08x]\n", nRet, aaa);

    if (nRet != 0)
    {
      GetMessage(&Msg, NULL, 0, 0);
      
      if (Msg.message == WM_THREADSTOP)
      {
  // スレッド停止メッセージ
  TRACE("停止Msg!\n");
  // スレッド終了
  break;
      }else if (Msg.message == WM_CHGSET){
  // 設定変更メッセージ
  TRACE("設定Msg!\n");
          ☆設定変更処理
  Sleep(100);
  continue;
      }

      Sleep(100);

      ☆ファイルの存在確認処理
      if (FileCount == 0)){
  Sleep(100);
  continue;
      }

      ☆ファイルがあった場合の処理
  ☆親ウィンドウ(GUI)にメッセージを送り内容を表示させる。

    Sleep(300);
  }

と、こんな感じにしてます。実行した結果ですが・・・

PeekMessage直前/GetQueueStatus():[0x00000000]
PeekMessage[nRet=0]/GetQueueStatus():[0x00000000]
送信完了
送信完了
送信完了
送信完了
PeekMessage直前/GetQueueStatus():[0x00080008]
PeekMessage[nRet=1]/GetQueueStatus():[0x00080000]
設定Msg!

一部ではありますが、ずっとこのような感じで続きます。
昨日の時点では「送信完了」と表示されても「設定Msg!」で表示されない
場合が多々あったのですが、今日は現象が起きていません。

「送信完了」で100回送られているので計400回送られている筈ですが
「設定Msg!」は一度しか表示されてません。
400回「設定Msg!」が表示されるべきだと思うのですが・・・。

ちなみに、GetQueueStatus()の引数にQS_SENDMESSAGEを入れて試して
みましたがメッセージ送信前後とも0が帰ってきました。
<MSDN>
上位ワードは、現在メッセージキューの中に存在するメッセージタイプ
(flags パラメータを参照)を示します。
</MSDN>
これはこれで?の気が・・・0x00400000が帰ってくるなら解るのですが・・・


Ban  2007-06-25 09:58:18  No: 65467

# C言語/Win32のお約束として、比較は0とやるのがセオリーです。
# PostThreadMessageは[0]か[非0]が返ります。仕様上、[1]が返る保証はないです。

VC6はもうMSのサポートも切れたので、手元に環境がないのですが、
提示コードをXPproSP2,VC7.1SP1(2003)でMFCダイアログで
試してみたところ(デバッグ版)、
……
PeekMessage直前/GetQueueStatus():[0x00000000]
PeekMessage[nRet=1]/GetQueueStatus():[0x00080000]
設定Msg!
送信完了
PeekMessage直前/GetQueueStatus():[0x00080008]
PeekMessage[nRet=1]/GetQueueStatus():[0x00080000]
設定Msg!
PeekMessage直前/GetQueueStatus():[0x00080000]
PeekMessage[nRet=1]/GetQueueStatus():[0x00080000]
設定Msg!
PeekMessage直前/GetQueueStatus():[0x00080000]
PeekMessage[nRet=1]/GetQueueStatus():[0x00080000]
設定Msg!
……
手元ではちゃんと取れてるようです。


Ban  2007-06-25 10:00:03  No: 65468

☆ファイルの存在確認処理
☆ファイルがあった場合の処理
☆親ウィンドウ(GUI)にメッセージを送り内容を表示させる。

私の手元にはこれらの処理がないのですが、
こいつらの中に悪さをする(内部でメッセージを使う)ものとかいませんか?


Ban  2007-06-25 10:02:21  No: 65469

# 連投申し訳ない。

そもそも「☆」の処理まで私のところでは到達してませんので、
無関係ですかね…。

ちなみに、VC6にはSP6を当てていますか。PSDKのバージョンは最新ですか。
実行環境のOSやCPUはなんですか。
などの基本的な部分は確認済みですか。


たばた  2007-06-25 19:35:57  No: 65470

>試してみたところ(デバッグ版)、
(中略)
>送信完了
>PeekMessage直前/GetQueueStatus():[0x00080008]
>PeekMessage[nRet=1]/GetQueueStatus():[0x00080000]
>設定Msg!
>PeekMessage直前/GetQueueStatus():[0x00080000]
>手元ではちゃんと取れてるようです。

「送信完了」は100回送っているんですよね?
何故「設定Msg」は1回しか表示されないのですか?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
100回送っているのであれば100回「設定Msg」が出る
のではと思うのですが。

>☆ファイルの存在確認処理
>☆ファイルがあった場合の処理
>☆親ウィンドウ(GUI)にメッセージを送り内容を表示させる。
>私の手元にはこれらの処理がないのですが、
>こいつらの中に悪さをする(内部でメッセージを使う)ものとかいませんか?

このあたりは一通りデバッグ済で、希望の動作でちゃんと
動いてくれてます。メッセージに関わる部分はGUIに送る所
ぐらいですが、実際にGUIに対してメッセージも送られて
表示も出来ているので問題は無いように思えます。

環境はWindows2000 VC6(SP6済)でPCもP4-2.4GHz メモリ768MBと
一般的なものです。PSDKは特に何かをインストールした経験はありません。
SP6のみでも対応出来ているものだと思っていましたが違うのでしょうか?


たばた  2007-06-26 03:46:19  No: 65471

この項目だけで異常にスレ消費しているのと、
Banさんにも長い間申し訳ないので、ひとまず
解決とします。

取り合えずはグローバルの変数でフラグを
受け渡ししてやりとりしようと思います。

ありがとうございました。


Ban  2007-06-26 09:31:50  No: 65472

「設定完了」ってなんですか?「送信完了」のこと?

あなたの提示ソースは、メッセージを100回送信した「後に1度だけ」
送信完了を表示するものですが、これが100回出ると期待しているので?

void CxxxDlg::OnBtnDummy() 
{
  // スレッドに変更を通知
  int i,n;
  for (i = 0; i < 100; i++)
  {
    n = RecvThreadHandle->PostThreadMessage(WM_CHGSET, 0, 0);
    
    if (n != 1) TRACE("PostThreadMessage_ERR!!\n");
  }
  
  TRACE("送信完了\n");
}


Ban  2007-06-26 09:33:22  No: 65473

# 設定完了って本当になんだ…見間違えたらしい…申し訳ないです…orz


Ban  2007-06-26 09:33:24  No: 65474

# 設定完了って本当になんだ…見間違えたらしい…申し訳ないです…orz


Ban  2007-06-26 09:47:21  No: 65475

# 二重投稿になってるし…orz
# 質問も閉じられているし、呑んでる日はダメっぽいのでこれを書いたら寝ます。

> 「送信完了」は100回送っているんですよね?
> 何故「設定Msg」は1回しか表示されないのですか?

ログ取得時、ボタンを押したのは一回だけですので、
WM_CHGSETは100回送っていますが、
送信完了は一回しか表示されません。

理由は、提示コードがそういうロジックだったから。

ちなみに、「設定Msg!」の方は100出てました。
最初にメッセージを100も投げつけるので、メイン側で「送信完了」が出る前に、
ワーカ側で既に「設定Msg!」のログが出始めて、先のログのようになりました。
# 勿論、これが交互に行われる保証はありません。
# この例では、OutputDebugString(TRACE)がディスパッチを誘発したのかも。


Ban  2007-06-26 09:58:26  No: 65476

追記:上記の設定Msg!100回というのは、当然
以下の1セットが100回続いて、以後は空になることを意味します。
1.PeekMessage直前
2.PeekMessage[nRet=1]
3.設定Msg!


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加