- - PR -
【VC#2005】PostThreadMessageを使う方法
1
投稿者 | 投稿内容 | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2007-07-10 17:43
いつもお世話になっております。
久しぶりにプログラムしていて思ったのですが、 下記ってどうなっているんでしょうか? ご存知の方いらっしゃいましたら教えて下さい。 『VC++のSendMessage』は、『C#のControl.Invoke』に対応し、 『VC++のPostMessage』は、『C#のControl.BeginInvoke』に対応しています。 では『VC++のPostThreadMessage』は、 C#ではどうやって実装したらよいのでしょうか? メッセージループをしていて随時メッセージを受信できるスレッド (=ワーカースレッドではない)を利用してプログラムしたいのですが、 C#ではどのように実装してやればよいのでしょうか? @スレッドからの画面Formへのアクセスは、Control.BeginInvokeを利用 Form←Thread Aフォームから既存のスレッドへメッセージングする方法は??? (どう実装するのでしょうか?) Form→Thread 以上、お忙しいとは思いますが、よろしくお願いいたします。 | ||||||||||||||||||||
|
投稿日時: 2007-07-11 00:46
こんばんは。
どうでも良いことですが・・・ 同期・非同期(受信側/呼び出し側スレッドがブロックされるかどうか)という意味では正しいと思いますが、 実装上はControl.InvokeもControl.BeginInvokeも、どちらもPostMessageが使われていますね。
少し順序立てて考えてみたいと思います。 まず、メッセージループを持つスレッドを作成するには そのスレッドでApplication.Runメソッドを呼び出す必要があると思います。 つぎに、FormやControlをもたないようなスレッドに処理させたい場合、 Application.AddMessageFilterメソッドで、直にウィンドウメッセージを処理するしかなさそうです。 と考えると、P/Invokeで直にWindows APIのPostThreadMessageを呼び出さないといけないのではないかと思います。 というわけでコードを書いてみました。 #つたないコードでスイマセン。.NET/C#のコードをほとんど書いたことないので。 Program.cs
Form1.cs
| ||||||||||||||||||||
|
投稿日時: 2007-07-11 16:19
早速の回答ありがとうございます。
非常に参考になりました。 (興味ですが、Control.Invokeの内部実装ってどうするとみれるんですか?) ただ私の質問の仕方がまずかったようなので 再度質問させてください。 C++では(Dialog-Thread間は、)メッセージ通信で非同期処理を実装する 実装モデルを提供しています。 C#ではThread側にメッセージ用に使用する関数”Invoke”のようなものが 見当たりません。 (Form側には、Control.Invokeがあります。) C#でForm−Thread間で非同期通信する際の実装モデルは どのようなものなのでしょうか? 正直、C#のThreadを無限ループさせて、排他したキューを実装すれば 自前で実現できますが、 ライブラリで用意されているのならばそちらを使用したいのです。 が、今までそういったサンプルを見たことがありません。 (『ワーカスレッドの例』、『同期オブジェクトで呼出側がブロックしてしまう例』 ばかり目にします。) で質問なのですが、 C#で上記のような実装をする場合のモデル(MSの提唱するデザインパターン) のようなものはあるのでしょうか? または、このようなケースでは皆さんはどのように実装されているのでしょうか? 教えて下さい。 以上、お忙しいとは思いますが、よろしくお願いいたします。 | ||||||||||||||||||||
|
投稿日時: 2007-07-11 16:51
「C++」ではないです。 メッセージ通信を提供しているのはWindowsです。
で、Win32のWindowはシングルスレッド用に作られているので、 異なるスレッドで作成されたWindowオブジェクトを処理することができません。 マネージできれいに処理するためにInvokeがあるんです。 メッセージ用・スレッド間通信用にあるわけではありません。 もしスレッド間通信ようにあるのでしたら Threadクラスにあるはずです。
MSの提唱する非同期のデザインパターンは IAsyncResultとイベントです。 スレッドはスレッドプールを用いるのを推奨しています。 つまり、非同期な処理をしたいなら、
といったことをしないように、 タスクを十分に細かくして、 タスクごとにスレッドプールを使えということです。
どうしてもメッセージループを回したいなら Tdnr_SymさんのおっしゃるようにApplication.Runを使うと思いますが、 「メッセージループをしていて随時メッセージを受信できるスレッドを利用したい」 と思ったことがありません。 常にタスクを実行しているスレッドと通信する場合は 普通に同期オブジェクトを使いますが、 常にタスクを実行するスレッドを作るのもまれで、 数値計算の場合だけです。 普通のアプリで本当に常にタスクを実行しているなら、 重くて熱くてやってられません。 C++でのWindowsアプリケーション開発の知識を 広く適用しすぎに聞こえます。 そもそもスレッド間通信にWindowsメッセージを使うのは ごく限られた状況だと思います。 | ||||||||||||||||||||
|
投稿日時: 2007-07-11 17:56
こんにちは。
Reflectorなどのツールで見ることができますが ご使用するのが良いか悪いかは、ご自身の判断にお任せします。
非同期メッセージパッシング的な機構が実現できれば Windowsのメッセージキューじゃなくてもよかったんですね^^; たしかに自作することはそんなに難しいことではないと思います。 私もある組み込みリアルタイムシステムで、非同期メッセージパッシング機構を 共有メモリ上にリングバッファを作って実現したことがあります。(.NETではないですが)
ウィンドウメッセージを使わない非同期メッセージパッシング機構が .NET Frameworkで提供されているのであれば、私も興味があります。 | ||||||||||||||||||||
|
投稿日時: 2007-07-11 19:42
To:れい様
回答ありがとうございます。 念のため、再確認させてください。 『スレッドを自作してメンバにオブジェクトを持たせて管理するような実装(私の実装モデル)』ではなく、 『どのスレッドで動作してもよいようなオブジェクト分けをして、CallbackをThreadPoolで実行させなさい(MS実装モデル)』 ってことですよね? 私の認識しているMVCモデルのC(コントローラ)は、デカ過ぎってことですね。 (オブジェクト指向的でない?) 個人的には、.NetFrameworkは謎の部分が多い (ThreadPool数の制約とかもあったはず)ので、 規模が大きいアプリではあまりCallbackとかクリアに 理解できていない部分は採用したくないなぁ というのが私の正直な感覚なのです。 (自分のスキル不足ですが...) 一応、MSの推奨モデルということなので、非同期Invokeで実装してみます。 (どのスレッドで実行されるかわからないモデルだと、 複雑なトランザクションを組むと、デッドロックとかって 発生頻度上がったりしないのかなぁとやや心配です) >C++でのWindowsアプリケーション開発の知識を >広く適用しすぎに聞こえます。 >そもそもスレッド間通信にWindowsメッセージを使うのは >ごく限られた状況だと思います。 これはご指摘の通りだと思います。 私は、アプリ開発経験がVC++6だけなので それが常識と思い込んでしまっているんだと思います。 To:Tdnr_Sym様 回答ありがとうございました。 『ウィンドウメッセージを使わない非同期メッセージパッシング機構が .NET Frameworkで提供されている』かどうかはわかりませんでした。 (おそらく、なさそう?ですね...) お二人とも、回答ありがとうございました。 勉強になりました。 | ||||||||||||||||||||
|
投稿日時: 2007-07-11 20:23
えと… メンバって何のメンバ? オブジェクトってなんのオブジェクト? オブジェクトの中にスレッド埋め込んじゃうってこと、かな? どっかのオブジェクトのメンバにスレッドを持たせるってこと、かな? すみません、まったくわかりません。
いや別にオブジェクトと同期とは関係なくって、 Taskみたいなオブジェクトつくってもいいし、他の方法でもいいし。 でも一度に長時間スレッドを動かしつづけるのはあまりよくなくて、 うまくタスクをわければ 数値計算とか負荷テスト以外ではほとんどなくなるはず。 もし一つのスレッドをずっと動かし続けたいなら自分でスレッド作ったほうが楽。 あとCallbackはThreadPoolのスレッドとは限らないです。 呼び出し元スレッドの場合もあるし。 ぜんぜん関係ない第3のスレッドの場合もあるし。
MVCってModel View ControllerのMVC? スレッドの話じゃなかったっけ? メインじゃないスレッドのほうもViewがあるなら 普通にそのスレッドでForm作ればいいのでは?
理解できていない部分を採用しないのは正しいと思いますが…。 「理解できていない部分を採用しない」且つ「.NetFrameworkは謎の部分が多い」 なら.Net Frameworkを使わないのが最良の解決法なのでは?
「どのスレッドで実行されるかわかってるモデル」を使えば気にしなくて良かったことを、 「どのスレッドで実行されるかわからないモデル」では気にしなければならなくなるかもしれませんが、 それは本来マルチスレッドプログラミングでは 解決しなければならないはずの問題だと思いますよ。 それをシングルスレッド風に処理してたから問題なかっただけで。 その分ウェイトがあってパフォーマンスが落ちてたのでは? |
1