C#のイベントとは? メッセージキューとの関係を解説

このQ&Aのポイント
  • C#ではイベントというものが利用されますが、これはMFC C++のウィンドウメッセージに似た仕組みです。イベントはメッセージキューにためられたメッセージが処理される際に呼ばれるものであり、ウィンドウハンドルを使用せずにウィンドウメッセージを送ることができます。
  • しかし、イベントとウィンドウメッセージは異なるものであり、割り込みとも異なります。入門書で使い方を学んだ方もいるかもしれませんが、仕組み的な部分が理解しづらいと感じることもあります。
  • そこで、C#のイベントとメッセージキューの関係について分かりやすく解説します。イベントの仕組みや使い方を理解することで、より効率的にC#を利用することができるでしょう。
回答を見る
  • ベストアンサー

C# のイベントって

C#を勉強中の者です。 むかし MFC VC++ を少しだけかじったことがありまして、 その中で、ウィンドウメッセージというものをよく利用していました。 C#ではイベントというものをよく利用するようですが、 これは MFC C++ でいうところのウィンドウメッセージと同じようなものでしょうか。 つまり、イベントというのは、メッセージキューにためられたメッセージが処理される際に呼ばれるものなのでしょうか。 仮にそうだとすると、イベントを発行するというのは、ウィンドウメッセージを送るのと同じようなものでしょうか。 ウィンドウハンドルとかないし、違うような気がしますね...。 でも、割り込みというのとは違いますよね...? 入門書は読んだんですが(いくつも読んだわけではないのですが...)、 使い方は書いてあってなんとなく理解はできた一方、 仕組み的なところがしっくりきません。 分かりやすい説明をいただけるとうれしいです。 よろしくお願いします。

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

  • ベストアンサー
回答No.3

> ウィンドウメッセージだと、 > PostするとキューにたまってFIFOで処理されますが、 > イベントを発行した場合はどうなんだろうと疑問に思った次第です。 ウィンドウメッセージとC#のeventは無関係です。 WinFormsの一部のイベントはウィンドウメッセージによって作り出されますが, これはC#のeventの本質とは関係しません。 > イベントの場合だと、 > 例えば複数のスレッドからイベントが発生した場合、 > あるイベントの処理中に別のイベントの処理が起こるとか...。 イベントの発生とは本質的にデリゲートの実行です。 public event EventHandler Foo; は private EventHandler _Foo; // 実際には<>とかが付いてアクセスできない名前が使われる public event EventHandler Foo { add { _Foo += value; } remove { _Foo -= value; } } ですし,上記に対して, Foo(this, EventArgs.Empty); は実際には _Foo(this, EventArgs.Empty); となっています。 つまり,イベントの発生とはデリゲートの通常の呼び出しに過ぎません。 このため,イベントハンドラの実行はイベントが実際に呼び出されたスレッドで実行されます。 # BackgroundWorkerのように,トリガとイベントが別のスレッド,ということはできる。 また,イベントハンドラがイベントのトリガを引けば当然イベントが発生します。 それを抑止することもあるでしょうけれども,それはトリガ側の実装次第になります。

ogu-ne
質問者

お礼

回答をありがとうございます。 そうですよね、ウィンドウメッセージとは関係ありませんね。 いまの知識では、教えていただだいたことを、まだ完全には理解できませんが、 なんとなくわかりました。 まだよく分かっていないせいもあって、 ウィンドウメッセージに比べて、 イベントに対して漠然とした不安があります。 その不安がうまく表現できない...。 ウィンドウメッセージだとキューにたまって FIFO が保障されるけど(Sendを除き)、 イベントはそのあたりがよく分からないのですが、 なにが問題に思えるのか自分でもよくまとまっていません。 とりあえずもう少しプログラミングをしつつ勉強してみます。 ありがとうございました。

その他の回答 (2)

  • lv4u
  • ベストアンサー率27% (1862/6715)
回答No.2

>>これは MFC C++ でいうところのウィンドウメッセージと同じようなものでしょうか。 C#でプログラムを作っていたときは、同じようなものと思ってやっていましたよ。 ちょっと標準ではない処理を実行する場合、メッセージを送ることもやりました。 >>ウィンドウハンドルとかないし、違うような気がしますね...。 C#でもウインドウハンドルの取得をやったりします。 >>仕組み的なところがしっくりきません。 入門書には、そういう部分は記述されていないと思います。そこまで記述したら初心者はついてこれないかも? 私の場合は、入門書やリファレンス本、C#文法書を見たあと、 ・究極のC#プログラミング/新スタイルによる実戦的コーディング ・C#によるコンポーネントプログラミング ・プログラミングADO.NET 2.0 ・プログラミング.NET Framework ・メタプログラミング.NET などを読みました。仕組み的な面は、「メタプログラミング.NET」を読まれるのがいいと思います。

ogu-ne
質問者

お礼

回答をありがとうございました。 たくさんの本を読まれているんですね。 やはりプロはそのくらい知識を持ってないとできないものなのでしょうね。 精進したいと思います。 と、言ってもそんなに開発の機会はないのですが。 ウィンドウメッセージだと、 PostするとキューにたまってFIFOで処理されますが、 イベントを発行した場合はどうなんだろうと疑問に思った次第です。 ウィンドウメッセージの場合は、 ひとつのメッセージの処理を終えてシステムに制御が戻るまで、 次のメッセージは処理されないけれども、 イベントの場合だと、 例えば複数のスレッドからイベントが発生した場合、 あるイベントの処理中に別のイベントの処理が起こるとか...。 そんなことはないですね。

回答No.1

C#のイベントは言語仕様化されたObserverパターンです。

ogu-ne
質問者

お礼

回答をありがとうございます。 言語仕様化されたObserverパターンですか...。 早速調べてみました。 モデル、というか、概念、というか、 そういうのは分かりました。 勉強が必要です。 ありがとうございました。

関連するQ&A

  • C# イベント処理

    C#初心者ですが、イベント処理で困っています。VB6ではフィールドにてEventを宣言し、RaiseEventでイベントを発行し、WithEventsを使って他クラスでそのイベントを受け取る事ができますが、C#でどうしたら良いかわかりません。デリゲートとイベントについて理解が出来ていないので、簡単な参考例で教えて頂けないでしょうか?

  • 「イベント」とは?

    私は組込みシステムエンジニアをしています。 私が知る「イベント」という用語は、 「コンピュータの内部または外部にて何らかの変化が発生した際にプログラムに発信される信号」 を指し、その「イベント」に対する処理を「イベントハンドル処理」等と呼んでいます。 上を具体的な例で言うと 「(1)ボタンをクリックする」→「(2)ポップアップメッセージが出る」 だとすると、(1)が「イベント」で、(2)が「イベントハンドル処理」です。 ところが、最近ゲーム業界の方と一緒にお仕事をすることになり、その方は「イベント」は、私が「イベントハンドル処理」を指す用語だと言うのです。 業界によって「イベント」は別の意味だということなのでしょうか。

  • WaitForMultipleObjectのイベントの処理について

    はじめまして。 現在.NET 2003環境のVC++にて開発を行っています。 そこで知恵をかして頂きたいのですが、 WaitForMultipeObjects関数で待機している場合、 引数で指定している複数のイベントオブジェクトが ほぼ同時にシグナル化した場合、イベントの取りこぼし が発生する場合ってあるのでしょうか。 <例> スレッドA     スレッドB      スレッドC           for(;;){ SetEvent([0])     res = WaitFor...  SetEvent([1])             SleepEx(100, FALSE);           } ・スレッドBが複数のイベントを待機 ・スレッドA、Cがイベント発行 ・この場合、A、Cでほぼ同時にイベントが発生された場合、  (1)A(またはC)発行のイベントを取りこぼす  (2)A(またはC)発行のイベントを処理したのち、   のこりのイベントを再度処理する(for(;;)でループしている為) 取りこぼしの可能性があるとしたら、対応方法もできれば 知りたいです。 以上、よろしくお願い致します。

  • ループを使わずに、特定時間にイベントを発生させたい

    VC2005で、MFCアプリを作成しています。 ループを使わずに、ある指定時間もしくは、1時間後など設定した時間にイベントが発生し、その中で処理を入れる(例えば、時間が来ましたなどのメッセージ)を表示させるプログラムが書きたいです。 一回だけで終わるのではなく、イベント発生後、今度は2時間後にイベントを発生させるようなこともしたいです。 何かわかりやすいサンプルでもありましたら、助かります。

  • 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#ではどういうふうに実現するのが一般的なのでしょうか? 上記のような例の場合、非同期で動作させたいと思うのですが...。 どなたか教えてください。 お願いします。

  • 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#FormのLoadイベントについて

    C#FormのLoadイベントのタイミングは、ウィンドウプロシージャで受け取るWM_XXXXのメッセージで表すと、どのメッセージに該当するのでしょうか。

  • 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言語でのWindowsプログラム

    C言語でウィンドウを作るプログラムを作っているときにふと思ったのですが、Windowsが発行したメッセージを処理する関数(ウィンドウプロジャーでしたっけ?)なのですが、あれはどこの時点で呼び出されているのですか? 教えてください

  • VC++ 2005 MFC ボタンの無効化

    VC++ 2005 MFC ボタンの無効化 現在スレッドを使ったプログラムを作成しています。 あるボタンを押すと、 親スレッド 1、RS232C受信スレッドを作成 2、RS232Cにデータを送信 3、WaitSingleObjectでイベント待ち 4、受信状態に応じた処理 子スレッド 1、サムチェック等確認して、受信が完了すれば   受信データを格納してCEventのSetEventを発行 というような処理の部分があるのですが、待っている間にウィンドウ内にある ボタンが押せてしまいます。厳密には、イベント待ちを抜けた時点で待っている 間に押せてしまったボタンの処理が走ってしまうのですが。 EnableWindow(FALSE)をやっても駄目でした。 何かいい方法がありませんか??すいませんがよろしくお願いします。