C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: メッセージポンプ機能を持ったワーカースレッドの実装


(過去ログ 106 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■63221 / inTopicNo.1)  メッセージポンプ機能を持ったワーカースレッドの実装
  
□投稿者/ ホエホエ (5回)-(2012/08/07(Tue) 18:18:37)

分類:[.NET 全般] 

いつもお世話になっております。

タイトルにもありますが自作メッセージポンプを持ったワーカースレッドを
作成したいのですが上手くいきません。

ある別アプリにWM_USER+αのメッセージID、返信先ウィンドウハンドルを送信すると
別アプリが同じメッセージIDでウィンドウハンドルへSendMessageするので
それをウィンドウプロシージャでなくてワーカースレッドで拾いたいのです。
本来はUIスレッドでメッセージを処理すべきだとは思いますが…

ちなみにワーカースレッドはThreadクラスを生成し、バックグラウンド動作させ
スレッド関数内で以下のようになっています。


   //別アプリウィンドウハンドル取得
   IntPtr pSendWnd = FindWindow( null, "TestProg" );


   IntPtr	pParamW = IntPtr.Zero;
   IntPtr	pParamL = IntPtr.Zero;

   //別アプリへメッセージ送信成功?
   if( SendMessage( pSendWnd, WM_USER + 1, pParamW, pParamL ) != 0 )
   {
      while( true )
      {
        //メッセージ取得成功?
        if( GetMessage( out Msg, IntPtr.Zero, 0, 0 ) > 0 )
        {
           if( Msg.message == WM_USER + 1 )
           {
            //TODO : ここで受信時処理をする
            break;
           }
           DispatchMessage( ref Msg );
        }
        else
        {
           //TODO : エラー処理をする
            break;
        }
      }
   }

SendMessageが成功し、別アプリが動作し応答のSendMessageを送信しているとこまでは
問題ないのですがそのメッセージを取得することができません。別アプリは側が
PostThredMessageに変えれば受信できそうな気もしますが、別アプリ側は改造できません。
何か上記コードでは動作しない何か原因があるのでしょうか?

ちなみに環境は
WindowsXP SP3
VisualStudio2008以降
です。

ご存知の方、教えてください。

引用返信 編集キー/
■63226 / inTopicNo.2)  Re[1]: メッセージポンプ機能を持ったワーカースレッドの実装
□投稿者/ 渋木宏明 (2回)-(2012/08/07(Tue) 22:11:54)
渋木宏明 さんの Web サイト
> ある別アプリにWM_USER+αのメッセージID、返信先ウィンドウハンドルを送信すると
> 別アプリが同じメッセージIDでウィンドウハンドルへSendMessageするので
> それをウィンドウプロシージャでなくてワーカースレッドで拾いたいのです。
> 本来はUIスレッドでメッセージを処理すべきだとは思いますが…

ワーカースレッド内でウィンドウ(不可視でもおk)を生成して、そのウィンドウでメッセージを受けるんではダメなんですか?

相手に返信先ウィンドウハンドルを与えて、そのウィンドウハンドル宛にメッセージが送られてくるなら、どうしたってウィンドウが必要です。(相手のプログラムに手を入れられるなら別ですが)

引用返信 編集キー/
■63236 / inTopicNo.3)  Re[2]: メッセージポンプ機能を持ったワーカースレッドの実装
□投稿者/ ホエホエ (6回)-(2012/08/08(Wed) 09:32:17)
渋木宏明さん>
ご返信ありがとうございます。

やはりウィンドウが必要になるのですね…別アプリのプログラムは
あるので動作仕様は分かるのですが、当方管理外のため変更不可でして…

今、作成しているソフトの構成上、エントリポイント開始後に最初に
対象となるワーカースレッドが起動して別アプリとのメッセージ送受信を
開始しているため、ワーカースレッド内でフォームを作成してしまうと、
後で呼ばれるApplicationクラスのSetCompatibleTextRenderingDefaultメソッドで
例外になってしまうのでフォームやコントロールは使いたくないと思ったのですが…
引用返信 編集キー/
■63251 / inTopicNo.4)  Re[3]: メッセージポンプ機能を持ったワーカースレッドの実装
□投稿者/ 渋木宏明 (4回)-(2012/08/08(Wed) 13:53:50)
渋木宏明 さんの Web サイト
> 今、作成しているソフトの構成上、エントリポイント開始後に最初に
> 対象となるワーカースレッドが起動して別アプリとのメッセージ送受信を
> 開始しているため、ワーカースレッド内でフォームを作成してしまうと、

GUI アプリで、UI と無関係に通信処理を実行してしまうのは得策じゃないです。
GUI アプリであるなら、UI スレッド主体で構造や処理順を考えないと思いがけないところでハマります。

> 後で呼ばれるApplicationクラスのSetCompatibleTextRenderingDefaultメソッドで
> 例外になってしまうのでフォームやコントロールは使いたくないと思ったのですが…

通信処理を UI スレッドと協調するように変更するのが最善です。
それが無理だと、ワーカースレッド内で Windows API だけを使ってウィンドウの生成からメッセージポンプ回すところまで実装するとか、ますます混沌を深めることになってしまうと思いますよ。

引用返信 編集キー/
■63265 / inTopicNo.5)  Re[1]: メッセージポンプ機能を持ったワーカースレッドの実装
□投稿者/ とっちゃん (1回)-(2012/08/08(Wed) 17:24:36)
とっちゃん さんの Web サイト
No63221 (ホエホエ さん) に返信
> ある別アプリにWM_USER+αのメッセージID、返信先ウィンドウハンドルを送信すると
> 別アプリが同じメッセージIDでウィンドウハンドルへSendMessageするので
> それをウィンドウプロシージャでなくてワーカースレッドで拾いたいのです。
> 本来はUIスレッドでメッセージを処理すべきだとは思いますが…
>
SendMessage は、特定のHWND(!=NULLなもの)に対してメッセージを送信するためのAPIです。

今回の場合、WPARAM, LPARAM に0をセットして送信しているので、0を指すウィンドウ(デスクトップウィンドウ)に対して送信しているか
別アプリ側がNULLチェックして、送信しないようにしているかのどちらかになっているはずです。


> SendMessageが成功し、別アプリが動作し応答のSendMessageを送信しているとこまでは
> 問題ないのですがそのメッセージを取得することができません。別アプリは側が
ということで、自分がSendMessageするところまでは成功していると思いますが、
その後別アプリは、宛先なしとして SendMessage していないか、何も考えずにNULLのウィンドウ(実質デスクトップに相当しますが)に対してメッセージを送っていると思います。

あと、SendMessage は同期処理ですので、戻ってきた後にメッセージループを回しても受信はできません。また、Send中はそのスレッドはシステムが待機状態に遷移させるため(SendMessage APIの内部で待機状態に移行するため)、メッセージの受信はおろか、スレッド自身がロックダウンした状態となっています。

別アプリは改造できないとなると、ウィンドウハンドルが必須なので、ウィンドウを作って送受信処理する以外の選択肢はありません。

そのウィンドウをどのスレッドで作成するかはアプリケーションの構造自身に依存するためどれがいいとは一概には言えませんが
別アプリとのやり取りにウィンドウメッセージを使う場合は、その多くがアプリケーションの寿命と一致するメインウィンドウをその媒体ウィンドウとしていると思います。

もし、メインウィンドウでということであれば、メインのフォームのコンストラクタあるいは、Loadイベントメッセージをトリガーとするのが良いと思いますよ。

引用返信 編集キー/
■63289 / inTopicNo.6)  Re[2]: メッセージポンプ機能を持ったワーカースレッドの実装
□投稿者/ PATIO (3回)-(2012/08/10(Fri) 13:44:39)
2012/08/10(Fri) 13:46:29 編集(投稿者)

内容を読んでいて思ったんですが、ワーカースレッドでウインドウメッセージのやり取りをしないといけない理由がわからないです。

書かれている内容からするとそのアプリにはウインドウが存在するようなので本来のウインドウでメッセージを受けて
処理自体はワーカースレッドに実行させるというのであれば、理解できるのですけれど。

ワーカースレッドが先に起動して通信をするとありますが、ウインドウメッセージを使って相手からのメッセージを
受け取るのであれば、受け側にウインドウがない事は致命的なのでそもそも双方向の通信は成立しません。
メインウインドウが表示されると困るのであれば、一旦非表示で作成しておいてメッセージのディスパッチは
ウインドウに任せるとかという方法は取れないのでしょうか?

ワーカースレッドでウインドウメッセージのやり取りを行う理由の部分の説明がないので
代替案を出すにしても見当がつけられないと思うのです。

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -