• ベストアンサー

スレッド中でウインドウのイベント(Windows)

カテゴリー違いかもしれませんが、 Windowsでスレッド中でウインドウを生成すると、 イベントの処理ができなくなります。 (たぶんもとのイベントループにメッセージがいって  そこで終わっていると思うのですが) これを避ける方法とかあるのでしょうか? メインループにメッセージを送ってそこでウインドウを 生成してもらうのが由緒正しい方法なのでしょうか? 用語とかむちゃくちゃかもしれませんが よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • BILLY-J
  • ベストアンサー率57% (60/105)
回答No.2

開発環境が判りませんが、VC系でMFC使用可能なら CWinThread クラス を使う事でメッセージループ付きのスレッドを作れます。 参考URL: http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vclib/html/_MFC_CWinThread.asp また、「ホントにそのスレッドで~~~する必要が有るの?」という 事を慎重に考えて設計しないとマルチスレッドの罠に嵌ります。 例えば motsuan さんの場合、ホントにそのサブスレッドから自前の ウィンドウ作って描画する必要が有るの? がポイントの1つです。 (要件的に、本当に必要なのかも知れませんが…) 別のアプローチとして、画面の生成や描画はメインスレッドに全てを 任せて、サブスレッドからは非同期処理の中で PostThreadMessage を 使いメインスレッドへ描画等の指示を送る、という方法は如何です? 但し PostThreadMessage は文字通り PostMessage なのでメッセージ を処理し終わったかどうかは判りません。 しかし、そのような同期取りが必要ならば尚更、メッセージによって タイミングを計るのは危険で、面倒でも一般的な同期オブジェクト等 を使う方が良いと思います。

motsuan
質問者

お礼

ご回答ありがとうございます。 下記のような状況なのですが、 インタープリタでスクリプトを読み込んで それに応じて、数値計算をやって (スクリプトに従ってウインドウを生成し) その結果をウインドウに描画しながら 人からのイベントを拾うようなことをやっています。 インタープリタ自体を別プロセスで動かしたいけど その制御や結果については人からの イベントにあわせて進めたいという考えで、 スレッドを使っています。 "Keep it simple and stupid"から離れつつあるような気がするので、ご指摘のとおり、本当に良い方法かどうか悩んでおります。 下記のように、現在はメインのスレッド(ウインドウのメッセージループ)にメッセージを送ってウインドウを生成し、それにメッセージを送って描画していますが、 なんとなく無理やりな感じがして質問してみました。 ともかく参考にさせていただきます。 いろいろ書かせていただいたので、他の方から回答が繰るかもと期待してもうちょっとだけ開いておきます。 お礼が遅くなって申し訳ありあませんが、もう少々お待ちください。

その他の回答 (1)

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

作成したスレッドの中で新たにメッセージループを作るんだと思いますが。

motsuan
質問者

お礼

ご回答ありがとうございます。 状況の説明が不足しておりました。 Win32APIでスレッドをつくって、 Win32APIでウインドウを生成しています。 その際におきる症状が上記のものです。 ウインドウハンドルを使って メッセージを送ることはできるのですが、 イベント関係の連絡が上手くいきません。 現状、もとのウインドウでウインドウのイベントループにメッセージを送ってウインドウを生成しています。 Windows以外のOSへの移植も考えているので Windowsのシキタリに則った構造ではなく汎用性=「普通こうだろう」というのが分かればよいなと思い質問しました。 ともかく、お礼が遅くなってしまいましたが、ありがとうございました。

関連するQ&A

  • C#でスレッド実行中のイベントについて

    メインフォームの「処理開始ボタン」をクリックすると別スレッドが起動して、そのスレッド中で重たい処理をさせ、処理中に「中断ボタン」をクリックすると中断してアイドル状態に戻る様なプログラムについてですが、 先ず、Invokeを使わずに直接スレッドを起動すると期待通りの動作となり、Thread.Sleep()中でもボタンクリックのイベントが発生します。 しかし、Invokeとデリゲートを使ったスレッドを起動させるとスレッドの処理が終了するまでイベントが発生せず、行ったきり状態になってしまいます。 処理ループ内にAplication.DoEvent()を入れるとイベントが発生する様になりますが、Thread.Sleep()中はフリーズ状態となります。 Invokeを使ったスレッドでも、Invokeを使わない場合と同じ動作をさせる方法があれば教えて頂けないでしょうか。 どうぞ宜しくお願いします。

  • マルチスレッド:スレッドの終了を検知する(Ruby)

    2つ以上のスレッドを生成・動作させ、それらが終了した時点で、メインに処理を移すといったことをRubyでしたいと思っています。 (スレッドが1つならば、メインをstopさせておき、スレッドの終了時に例外処理などを使ってrunさせる方法は思いつくのですが。。) 一つ考えたのは・・・ カウンタ変数をつくり、一つのスレッドが終了したらその値を増やす。 メインではwhileループによってその値を常に数えて、全スレッドの終了を把握する。 ただ無駄にwhileループを回してしまいます。。 一般的な効率の良い手段等あるのでしょうか?

  • CPU資源をなるべく消費しないでイベントを待機する

    こんにちは。 VC++2008Exressを使用して、以下のようなプログラムを作成したいと思います。 初心者で、どうやって作成すれば良いのか悩んでおります。 参考になるものなどありましたら、ご教授ください。 Windowsアプリケーション Win32API メッセージループ内でWaitForSingleObjectなどのイベントを待機する関数を使用して イベントを待つようにしたいのですが メッセージループ内でメッセージも待機できイベントも待機できるような方法はないでしょうか? 今のところ、実現はしておりませんが検討しているのは メッセージ待機用のスレッドを作成して、GetMessageで待機して メッセージがきたら、SetEvent関数でメインのメッセージループ内の WaitForSingleObjectを返す。 また、別のメッセージ以外のイベントを監視するスレッドを作成して WaitForSingleObjectで監視してイベントが来たら、さきと同じイベントを SetEvent関数を使用しメインのメッセージループ内のWaitForSingleObjectを返す。 という感じでメッセージとイベントをメッセージループ内で監視するようにするしか 分かりません。 その他、簡単な関数で実現可能なものなどありませんでしょうか? WaitForMultiObjectsとか、MsgWaitForMultiObjectsやら調べてみましたが、いまいち使い方が。。。。 また、スレッドは監視イベントが来るたびに終了させた方がよいのでしょうか? それでは、またスレッド作成を繰り返すので効率悪い気がします。 無限ループで監視させた方が良いのではと思いますが、CPU資源的には・・・。 というようなことで悩んでおります。 どうか、ご教授ください。よろしくお願いします。

  • スレッドの安全な終了のさせ方

    スレッドの安全な終了のさせ方  メインスレッドにてCreateThread命令を使い、あるサブスレッドを作りました。 このサブスレッドは内部でmallocを使い動的に配列領域を確保して その配列領域をforループ等で「かなり時間の掛かる処理」として繰り返し アクセスしています。 ループが終了した時に「free」を実行してmalloc領域を開放しています。 アプリ終了時にメインスレッドからこのサブスレッドを終了させるのに メインウインドウにWM_DESTROYメッセージが送られた時、これまで単に そこで「CloseHandle(hSubThread);」とだけ書いていたのですが、 もしかしたらこれでは場合によっては(サブスレッドがループ処理中だったら) malloc領域が開放されずにリークしてしまうのではないかと思いました。  そこでイベントオブジェクトを使い、サブスレッドがループ処理中の 時には非シグナル状態にして、ループが終了しfreeで領域を開放した後 シグナル状態にするということにして、メインスレッドはそれを WaitForSingleObjectで待つという構造にしました。 ところが「メインスレッドに待ちを作るな」という言葉通り、これでは 上手く行きませんでした。サブスレッドはその時間の掛かる処理の 最中でSendMassage等でメインスレッドの処理を促すような命令を (例えばその処理の進捗状況を表示するなど)を幾つも行っていたので、 もしWaitFor~でメインを待たせると「サブスレッドの処理も進まなくなり 結果両方がロックして動かなくなってしまう」という悲しい状況に 嵌ってしまうのです。 SendMessageを徹底的に無くすということも考えたのですが、 (例えばPostMessageに書き換えるなどもやってみたのですが、これは 全く意図した動作をしてくれない場合もあり)、別の方法では どうしても代替できないケースもあって、全て消すというのは 現実的ではないのかもと。。  このようなサブスレッドを安全に終了させるにはどうしたら良いでしょうか? あるいは単にデストロイ時にCloseHandleとするだけでも良いのでしょうか?

  • 「UIスレッド」「マルチスレッド」の違い

    Androidで、「UIスレッド」「マルチスレッド」の違い、を教えてください。 ■下記理解で合ってるでしょうか? Androidは、「シングルスレッド」の「UIスレッド」モデルなので、それを「マルチスレッド」で動かそうとすると、「ワーカースレッド」で処理する必要がある ・「マルチスレッド」=「マルチタスク」? ・「UIスレッド」とは、メインスレッドが「GUI (グラフィカルユーザーインターフェイス) 処理」を行うものを指す? ・つまり、「Android」=「UIスレッド」? ・「UIスレッド」って何の用語? Androidに特化した用語? それともJAVAの用語? あるいはそれ以外?

    • ベストアンサー
    • Java
  • VC++ メインループでのイベント監視方法

    こんにちは。 VC++2008Expressでプログラムをしようと思っている初心者です。 以下、変な疑問があり、お尋ねしたいと思います。 よろしくお願いします。 Windowsアプリケーション Win32API クラスで別スレッドを作成して、そのスレッドからのイベントを WinMainループで受け取る方法ですが 通常皆様はどういう風にするのでしょうか? クラスは、その他のプログラムでも流用可能で様々なアプリに対応しやすいようにしあげたいのですが。。 別スレッドでイベント発生時にWinMainにどのように教えるのが普通のやり方なんでしょうか? 僕の考えでは、WinMain関数内のループ内で常時イベント発生していないか 以下のように監視させるか eventloop el; while(GetMessage(&msg,NULL,0,0)) {   TranslateMessage(&msg);   DispatchMessage(&msg);      if(el::boolEvent){     イベント処理へ   } } とするのが良いか? これだとクラスの関数、変数の使い方さえ分かるようにしておけば流用は簡単 なのかなと思いますが。。 メインのループ内にこんな監視を入れるようなプログラムをみたことないので ナンセンスなのではと思います。 次に考えられるのは、クラスのイベント発生で作成したSendMessageを送って メッセージ処理でイベント処理をさせるのが良いのかなって思いますが これだと、流用するときに対応したMessage(キュー?ですかね)を作成しないといけなく 私的に分かりにくいなーって思います。。。 変なことで悩んで先に進まないのですが、皆様はどのようにコーディングされるのでしょうか? ちなみにイベントというのは、RS232Cで受信があって、そのデータを加工したあとで メモリに格納して格納しましたよってイベントです。 どうかよろしくお願いします。

  • C++ビルダーでイベント付きスレッドクラスを作成したい

    C++系(主にボーランドビルダー)でVBの様なイベント付きクラスを作成したいのです。 単なるスレッドクラスの定義は: //---------------------------------------------- // クラス // スレッドクラスより派生 //---------------------------------------------- class CUserClass : public TThread { private: AnsiString aa; HANDLE hr; // ハンドル protected: HWND FormHandle; // 親フォームハンドル void __fastcall Execute();// スレッドメイン処理 public: __fastcall CUserClass(bool,AnsiString ,HWND ); // コンストラクタ __fastcall ~CUserClass(); // デストラクタ }; でいいのですが・・・。 何かクラス側で変化があったとき、クラスを使う親側モジュールにイベントを発生させたいのですが。 クラス側から親側に SendMessage( 親側ハンドル, 送りたいメッセージ, 0, 0 ); でメッセージを送る方法があるのですが、これだと親側がクラスでないといけないし、送りたいメッセージが固定となるし・・・。 よい方法を教えてください。

  • C# スレッドから親ウィンドウへの通知の方法は?

    昔、MFC C++を少しかじったことがあります。 今、システム部門のお手伝いに駆り出され、 C#を勉強しながら久しぶりにプログラミングをしています。 スレッドから、そのスレッドの呼び出し元である親ウィンドウに対し、 状態の変化を通知するような場合、 C#ではどのように実現するのがふつうなのか教えてください。 例として、以下のような簡単な処理を考えます。 あるダイアログウィンドウに、2つのボタン[Start][End]があるとします。 初期状態では、[Start]が有効、[End]が無効です。 [Start]を押すと、複数のスレッドを起動し何かしらの処理を開始します。(*1) [End]を押すと、それらのスレッドに方法はともかく終了指示を送ります。(*2) (*1)ですべてのスレッドが起動すると[End]を有効/[Start]を無効とし、 逆に(*2)ですべてのスレッドが終了すると[Start]を有効/[End]を無効とします。 これらの処理を行うため、各スレッドは、呼び出し元親ダイアログウィンドウに対し、 起動直後には起動した旨を、終了直前には終了する旨の通知をします。(*3) ダイアログウィンドウでは、各スレッドからのこれらの通知を受け取り、 すべてのスレッドから通知が届き終わった際に、 [Start]や[End]のEnabledを操作して有効化/無効化します。 このとき、(*3)では、MFC C++では、WinPostMessage というものを使い、 ウィンドウメッセージ(WM_***)を送って通知する方法を利用していました。 C#でもPostMessageは使えるようなのですが、あまり使いやすくないようです。 これは、そもそもあまり使うものではないためだと思います。 現在はイベントを使っています。 PostMessageのようなものの場合はキューを介しますから、 postする側とメッセージを受け取る側は非同期になりますが、 イベントの場合は一連の処理を終えてイベントの呼び出し元に戻るまで復帰しませんよね? そこで質問なのですが、このような処理の場合、 つまり、スレッドから親ウィンドウへの通知は、 C#ではどういうふうに実現するのが一般的なのでしょうか? 上記のような例の場合、非同期で動作させたいと思うのですが...。 どなたか教えてください。 お願いします。

  • [Windowsプログラミング] スレッドでリアルタイムにキーボード入力を処理したいのですが

    いつもお世話になっております。 最近Windowsプログラミングを始めたばかりです。 今スレッドの勉強をしているのですが、キーボードの入力をスレッドが処理したいと考えております。 受け渡しでは生成時点での入力しか処理できず、うまくいきません。 プロシージャとスレッドでリアルタイムにデータをやり取りする方法はないでしょうか? ご指導よろしくお願いします。

  • java のスレッドについて

    java のスレッドについて javaでスレッドを作って処理をさせたいと思います。 メインのクラスでスレッドAを呼び出し、スレッドAで計算をしてその結果をメインのクラスで利用したい場合、一番簡単な方法は何でしょうか? なお、メインのクラスは、 while (Thread.isAlive()); な感じでスレッドが終わるまで処理を止めておきたいと思います。 簡単なコードを書いていただけないでしょうか?

    • ベストアンサー
    • Java

専門家に質問してみよう