デリゲートとイベントの関係(VB.NET2005)

このQ&Aのポイント
  • VB2005の本に書いてある内容が理解できません。誰か助けてください!イベントとデリゲートの仕組み .NETイベントが内部ではデリゲートとして処理されることを理解すれば、その威力を存分に引き出すことができます。
  • もう少し厳密に言うと、イベントを発行するクラスには、そのイベントをサブスクライブするクライアントすべてをポイントする、プライベートデリゲートフィールドが定義されています。イベントが発行されると、.NETのイベントインフラストラクチャによって該当するデリゲートフィールドのInvokeメソッドが呼び出されます。そして、Invokeメソッドからすべてのクライアントにイベントが通知されます。
  • このことは、.NET Frameworkで定義されているイベントごとに対応するデリゲートが存在することからもうかがい知ることができます。[オブジェクトブラウザ]を使用すれば、それを確認できます。たとえば、第2引数としてEventArgsオブジェクトを受け取るイベントはすべて、内部ではSystem.EventHandlerデリゲートを通じて管理されます。ほとんどのWindowsフォームコントロールが公開するKeyPressイベントは、KeyPressEventHandlerデリゲートによって処理されますが、このデリゲートは、第1引数としてObject、第2引数としてKeyPressEventArgsオブジェクトを受け取るSubプロシージャをポイントします。
回答を見る
  • ベストアンサー

デリゲートとイベントの関係(VB.NET2005)

VB2005の本に書いてある内容が理解できません。 誰か助けてください! ---------- イベントとデリゲートの仕組み  .NETイベントが内部ではデリゲートとして処理されることを理解すれば、その威力を存分に引き出すことができます。 もう少し厳密に言うと、イベントを発行するクラスには、そのイベントをサブスクライブするクライアントすべてをポイントする、プライベートデリゲートフィールドが定義されています。 イベントが発行されると、.NETのイベントインフラストラクチャによって該当するデリゲートフィールドのInvokeメソッドが呼び出されます。そして、Invokeメソッドからすべてのクライアントにイベントが通知されます。  このことは、.NET Frameworkで定義されているイベントごとに対応するデリゲートが存在することからもうかがい知ることができます。 [オブジェクトブラウザ]を使用すれば、それを確認できます。 たとえば、第2引数としてEventArgsオブジェクトを受け取るイベントはすべて、内部ではSystem.EventHandlerデリゲートを通じて管理されます。 ほとんどのWindowsフォームコントロールが公開するKeyPressイベントは、KeyPressEventHandlerデリゲートによって処理されますが、このデリゲートは、第1引数としてObject、第2引数としてKeyPressEventArgsオブジェクトを受け取るSubプロシージャをポイントします。 ---------- 全体的にちんぷんかんぷんですが特に「サブスクライブ」などがわかりません よろしくお願いします。

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

  • ベストアンサー
  • todo36
  • ベストアンサー率58% (728/1234)
回答No.1

実例を挙げれば分かりやすいかな。 VBは苦手なのでC#で説明します。 -----イベントの基本形------------ //イベントを発行するクラス public class MyControl : Control //※1 { private event EventHandler myEvent = null; //※2 public event EventHandler MyEvent //※3 { add { myEvent += value; } remove { myEvent -= value; } } protected void OnMyEvent(EventArgs e) { if (myEvent != null) myEvent(this, e); //※4 : myEvent.Invoke(this, e)と同値 } protected override void WndProc(ref Message m) { if (何らかのタイミングで) OnMyEvent(EventArgs.Empty); //※8 base.WndProc(ref m); } } //イベントを使用するクラス public partial class Form1 : Form //※5 { private MyControl myControl1; private void Form1_Load(object sender, EventArgs e) { myControl1.MyEvent += myControl1_MyEvent; //※6 } public void myControl1_MyEvent(object sender, EventArgs e) //※7 { //Control.MyEventのイベント処理 } } ----------- イベントを発行するクラス(※1)には、そのイベント(※3)をサブスクライブする(※6)クライアント(※5)すべてをポイントする、 プライベートデリゲートフィールド(※2)が定義されています。 イベントが発行されると(※8)、.NETのイベントインフラストラクチャによって該当するデリゲートフィールド(※2)の Invokeメソッドが呼び出されます(※4)。 そして、Invokeメソッドからすべてのクライアントにイベントが通知されます(※7が実行される)。 //イベント サブスクリプションとサブスクリプションの解除 //http://msdn.microsoft.com/ja-jp/library/ms366768.aspx

trap1130
質問者

お礼

サブスクライブとはイベントを受け取る、イベントを通知される、という解釈でしょうか。 スッキリしました。 ありがとうございます!!

関連するQ&A

  • c# イベント用デリゲートの引数

     こんにちは。c#初心者です。  今回はイベントに用いるためのデリゲートの引数に関する質問です。  通常、「System.Windows.Forms.Control」のイベントで用いられているデリゲートの引数は全て  void SampleHandler(object sender, SampleEventArgs e)  のようになっていますが、コントロール以外のクラス(System.Windows.Forms.Controlから派生しないクラス)、例えばコレクションクラスのようなものでも同じように「EventHandler<T>」デリゲートを使わなければならないのでしょうか?  それともう一つ質問です。コントロールクラスでのイベントの引数は  SampleHandler(object sender, …  のようにせずに  SampleHandler(SampleControl sender, …   としてはいけないのでしょうか? (いけないと思いますが…)  質問は以上の2点です。どなたか詳しい方がいらっしゃいましたら教えていただけませんか?

  • VB.NETユーザーイベントの使い道は?

    ユーザーイベントがなくてもデリゲートを使えばいいと思うのですが VB.NETでRaiseEventを使うのはどんなときですか? 内部ではイベントもデリゲートも同じ処理をしているのに わざわざRaiseEventキーワードが用意されているのはそれなりの理由があるんですよね?

  • Visual Basic 2005 でのデリゲート、Invokeについて

    卒論の関係で、Visual Basic 2005 Express Editionを使用して、システムを構築しています。 スレッドまたはフォームが複数あるため、デリゲートを使用することになったのですが、invokeの対象であるメソッドで引数を使用することはできるのでしょうか? 引数なしの場合、現時点では次のように記述しています。 A.show() A.Invoke(New MethodInvoker(AddressOf A.Status_Timer)) Public Sub Status_Timer()   処理 End Sub MethodInvokerは、デリゲート宣言なしでinvokeを使えることができ、本来?のデリゲート宣言して、invokeを使う場合は以下のようになります。 A.show() A.Invoke(New SetFocusDelegate(AddressOf A.Status_Timer)) Delegate Sub SetFocusDelegate() Public Sub Status_Timer()   処理 End Sub ここで、Status_Timer()に引数を指定して、たとえば、 Public Sub Status_Timer(ByVal data As integer)   処理 End Sub とした場合、invokeでの記述がうまくいきません。 もともと、invokeではそんなことはできないかもしれませんが、何か方法ありますでしょうか?現時点では、引数を使用することができないので、スレッドまたはフォーム間で、プロパティを使用して、情報を渡しています。以下のような形です。できれば、プロパティを使用したくないのですが・・・ Public Property test() As state Get Return _test End Get Set(ByVal value As state) _test = value End Set End Property

  • eventの概念が理解できません

    こんにちは。オブジェクト志向でVB、C#を学んでいます。デリゲートを理解してeventについて学んでいますが、よく理解できません。 イベントとは、「あるアクションが発生したことを自動的に通知するための仕組み」と本にあります。 さらに、「送信側オブジェクトのイベント(と呼ばれるクラスメンバーに、受信側のイベントハンドラー(と呼ばれるメソッド)を登録します。」とあります。 下記が本に載っているコードです。 私が理解できているのは、 ・戻り値が無し、引数をとらないメソッドを参照するオブジェクト。MyEventHandlerというデリゲートを宣言 ・戻り値が無し、引数をとらないメソッドを参照するオブジェクト。SomeEvent変数を宣言 ・MyEvent型のevt変数の宣言 理解できないのは、 evt.SomeEvent += Handler;。何をやっているかわかりません。 ここをわかりやすくお教え頂けませんでしょうか? using System; //MyEventHandler型を宣言。ここは理解できます。 delegate void MyEventHandler(); class MyEvent{ //イベントの宣言。EventHandler型の変数、SomeEvent。 public event MyEventHandler SomeEvent; public void Fire(){ if(SomeEvent !=null) SomeEvent(); } } class EventDemo{ static void Handler(){ //←イベントハンドラー Console.WriteLine("Event occurred"); } static void Main(){ MyEvent evt = new MyEvent(); evt.SomeEvent += Handler; evt.Fire(); } } また、もう一点お教え下さい。フォーム上のボタンをクリックした時に、メッセージを表示するようなイベントはどのような形で動いているのでしょうか? senderはイベントの発生元のオブジェクトがそのまま入っていて、eはイベントの補足情報が入っているのは理解しました。 ボタンをクリックした時に、ボタンクラスから何らかの情報が送られてきて、それをsenderとeで受取ると思うのですが、これのどこにeventとデリゲートが関わってくるのでしょうか? 何かモヤモヤしてeventがわかりません。 宜しくお願い致します。 private void btn_Click(object sender, EventArgs e) { messagebox.show("hello"); }

  • デリゲートについて

    初心者です。デリゲートを初めて使うのですが、 スレッド処理でWebClientでイベントハンドラを作成した後、 以下の Delegate Sub MyDelegate() Private Sub downloadClient_DownloadProgressChanged(ByVal sender As Object, ByVal e As System.Net.DownloadProgressChangedEventArgs) If InvokeRequired Then Invoke(New MyDelegate(AddressOf DownloadProgressA)) '終わり Else ProgressBar1.Value = e.ProgressPercentage Label1.Text = e.ProgressPercentage & "%" End If End Sub でDownloadProgressAには ProgressBar1.Value = e.ProgressPercentage Label1.Text = e.ProgressPercentage & "%" と書いたのですが、 メソッド 'Private Sub DownloadParmertar(sender As Object, e As System.Net.DownloadProgressChangedEventArgs)' に、デリゲート 'Delegate Sub MyDelegate()' と互換性があるシグネチャがありません とエラーが発生します。 スレッド処理やDelegate、Invokeを初めて使うので よく分かりません。どうすれば進行度を処理表示 出来るでしょうか…。 お優しい方教えて下さい。

  • 実行時に確定するメソッドを呼び出す方法について

    invoke()メソッドや、Methodクラスを 使用するなど。以前に小耳にはさんだ。記憶があります。 以下の3つの引数から 動的に該当メソッドを呼び出す。 処理を実装コードがすぐだせる方がいると 助かります。 Object foo(Object obj, String methodName, Collection param) (1)該当オブジェクト getClass()などで、該当クラスを動的に  特定。 (2)、(1)が保有しているメソッドのうち、 発行したいメソッドの名前 (3) parmには1要素ごとに2要素のObject[]型を   を格納して、 Object[0]の要素にかんしてはが引数の型についての完全修飾クラス名をあらわすString型。   Object[1]については実際に入っている値。 上記3つの引数をうけとって内部で getClass()とかつかって 必要な情報はすべて実行時に動的に 取得して objの該当オブジェクトを 発行し、foo()メソッド自体の 返却値はそのメソッドの返却値とする という ロジックの実装のサンプルがあると。 とても、うれしいです。 じゃ、void型が返却の時どうすんねん。 とか、staticの時どうすんねん。 とか、その変のアイデア持ってる 人がいるととてもうれしい。 以上

    • ベストアンサー
    • Java
  • 実行時にコントロールのイベントの登録/解除を、イベントハンドラのメソッドをあらかじめ知っていないロジックから実施する方法

    実行時にコントロールのイベントの登録/解除を、イベントハンドラのメソッドをあらかじめ知っていないロジックから実施する方法 通常、実行時にコントロールにイベントの登録/解除 を行う際は。 AddHandler 対象コントロール.イベント名, AddressOf メソッド RemoveHandler 対象コントロール.イベント名, AddressOf メソッド や AddHandler 対象コントロール.イベント名, メソッドのデリゲート型 RemoveHandler 対象コントロール.イベント名, メソッドのデリゲート型 を行うと思います。 しかし、この方法では、これを実施するロジックが AddressOf メソッド や メソッドのデリゲート型 を知っていなければなりません。 そうではなく、それをあらかじめ、知っていなくても 対象コントロール から AddressOf メソッド や メソッドのデリゲート型 に該当するオブジェクトを取得するなどして、 実施できる方法を教えてください。 言語は、.NET系であれば。。 VB.NET, C#, C++のいづれかでもよいです。 できさえすればよいです。 J#とか、Delphi.NETとかマイナーなのは、厳しいです。 なお、C++でもしできるのであれば。 2003のマネージC++と、 2005のC++/CLIの両方について知りたいです。 以上、よろしくお願いします。

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

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

  • デリゲートで子から親フォームのメソッド実行について

    お世話になります。 .NET C#で開発をしております初心者です。 下記の様なデリゲートで子フォームから親フォームのメソッドを実行 させようとしています。 すると、parent2.MeisaiSyutoku(); の部分で エラーが発生してしまいます。 (エラー内容:NullReferenceExceptionはハンドルされませんでした。        オブジェクト参照がオブジェクト インスタンスに設定されていません。) 同じ子フォームで(親フォームは違いますが)、もう1つデリゲートをやっているのですが それも何か悪かったりするでしょうか。 下記のデリゲートで、デリゲート(2)はちゃんと実行されますが、デリゲート(1)の方でエラー となってしまいます。 どなたかご親切な方、違う方法でも構いませんので、子フォームから 親フォームのメソッドを実行する方法を教えて下さいます様、 宜しくお願い致します。      記 デリゲート(1) 子フォーム側 parent2; //親フォームの参照 public void setOya2(案内書 parent) { this.parent2 = parent; //親フォームから参照を受け取って保持する } private void button2_Click(object sender, EventArgs e) { ~イベント処理~ parent2.MeisaiSyutoku(); //案内書.csのメソッド実行 } 親フォーム側 private void button4_Click(object sender, EventArgs e) { Global.openMOTO = 1; 台帳 n台帳 = new 台帳(); n台帳.setOya2(this); n台帳.Show(); } private delegate void ctlFromChild(); public void MeisaiSyutoku() { new Thread(new ThreadStart(delegate { Invoke((ctlFromChild)delegate { Get_MeisaiSyutoku(); }); })).Start(); } デリゲート(2) 子フォーム側 送り状作成 parent1; //親フォームの参照 public void setOya1(送り状作成 parent) { this.parent1 = parent; //親フォームから参照を受け取って保持する } private void fpSpread1_CellDoubleClick(object sender, CellClickEventArgs e) { ~イベント処理~ parent1.changeTextBox4(zOtodokeSaki);         } 親フォーム側 private void button1_Click(object sender, EventArgs e) { Global.openMOTO = 0; 台帳 n台帳 = new 台帳(); n台帳.setOya1(this); n台帳.Show(); } private delegate void ctlFromChild(); public void changeTextBox4(string str) { new Thread(new ThreadStart(delegate { Invoke((ctlFromChild)delegate { this.textBox4.Text = str; }); })).Start(); }

  • C# イベント処理

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

専門家に質問してみよう