質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.47%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

イベントハンドラ

マウスのクリックなどの特定の事象(イベント)が発生した時に実行される処理のことをイベントハンドラと呼びます。

Q&A

解決済

3回答

1593閲覧

C# イベントハンドラを呼び出す際の内部処理

senkei_river

総合スコア15

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

イベントハンドラ

マウスのクリックなどの特定の事象(イベント)が発生した時に実行される処理のことをイベントハンドラと呼びます。

0グッド

0クリップ

投稿2020/05/13 07:39

最近、C#のイベントハンドラを使って実装しているのですが、内部的にどのように処理されてるかがイメージできません。
例えば、C#で下記のようにTimerクラスのインスタンスにfunc関数をイベントハンドラとして登録しているのですが、内部的にはこのfunc関数の実行トリガーは、ポーリングで実現しているのでしょうか、それともobserverパターンで実現しているのでしょうか。

DispatcherTimer timer= new DispatcherTimer(); timer.Tick += func();

また、この他にも内部処理が知りたい場合、有用なサイトや本等、ご存知の方いらっしゃいましたらご教授いただけたら幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

発砲している場所は
.NET Core wpf/DispatcherTimer.cs at master · dotnet/wpf
.NET Framework DispatcherTimer.cs
ですね。

追っていくとWin32SetTimerになっているようですが、この先はわかりません^^;

投稿2020/05/13 11:03

TN8001

総合スコア9363

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

昔の Microsoft のチュートリアルで自分的に参考になった記事のコードが残っていたのでご参考に貼っておきます。サイトはすでにリンク切れで読めません。

// イベントとは、オブジェクトでクライアントに有益な事象が発生したときに、クラスからクライ // アントへ通知する方法のこと。 // // イベント使用の典型的な例は Windows フォームのコントロール。通常、インターフェイスのコ // ントロールを表すクラスには、ユーザーがコントロールに対して何らかの操作 (ボタンのクリッ // クなど) を行ったときに通知されるイベントが設定されている。 // // イベントの宣言には、デリゲートを使用する。イベントが発生すると、クライアントによって // フックされたデリゲートが呼び出される。 // 2015/2/7 以下のページを見つけたのでメモしておく: // 方法 : .NET Framework ガイドラインに準拠したイベントを発行する (C# プログラミング ガイド) // https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/events/how-to-publish-events-that-conform-to-net-framework-guidelines // 方法 : 派生クラスから基本クラス イベントを発生させる (C# プログラミング ガイド) // https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/events/how-to-raise-base-class-events-in-derived-classes using System; using System.Collections; namespace MyEventTest { // 宣言されていない場合は、最初にイベントのデリゲート型を宣言する必要がある。sender // はイベントが発生したオブジェクトへの参照。e はイベントデータが格納されているオブ // ジェクトへの参照。 // ライブラリの EventHandler を使う場合は、宣言済みらしく、この宣言は不用。 // 引数はライブラリの EventHandler と合わせているが、このサンプルでは使っていないの // で、ChangeEventHandler(引数なし) として書き直しても同じ結果になる。 public delegate void ChangedEventHandler(object sender, EventArgs e); public class ListWithChangedEvent : ArrayList { // イベントの宣言 // event キーワードに注意。 // クラスの外からはフィールドのように見える。ただし、アクセスには制限があり、実行で // きるのは、以下の処理だけ。 //  ・新しいデリゲートの結合 // ・(結合されている場合は)デリゲートの削除 // これらの処理には、+= および -= 演算子を使用する。下記の EventListener クラス参照 public event ChangedEventHandler Changed; // イベントの起動 // デリゲートをイベントにフックしているクライアントがない場合、フィールドは null に // なる。それ以外の場合は、イベント起動時に呼び出すデリゲートへの参照となる。このた // め、一般にイベントが起動される場合はまずこのフィールドが null かどうかを調べ、そ // の後イベントを呼び出す。 // イベントは、イベントを宣言したクラスの中からしか起動できない。イベントを起動する // protected メソッドを作成しておき、このメソッドを呼び出すことによって、派生クラスが // イベントを起動できる。さらに柔軟性を持たせるために、起動メソッドを virtual とし // て宣言することも多くある。これにより、派生クラスは、そのメソッドをオーバーライド // できる。 protected virtual void OnChanged(EventArgs e) { if (Changed != null) Changed(this, e); } // リストへの追加、リストのクリア、リストの要素への代入の際にイベントを起動(具体的 // には EventListener が Changed に結合したメソッド ListChanged を呼ぶ)。 public override int Add(object value) { int i = base.Add(value); OnChanged(EventArgs.Empty); // Empty の他に何がある??←無い。下記の説明を参照 return i; } // <ヘルプの EventArgs クラスの説明> // このクラスにはイベント データは格納されません。このクラスは、イベントの発生時にス // テータス情報をイベントハンドラに渡さないイベントによって使用されます。イベントハン // ドラがステータス情報を必要とする場合、アプリケーションは、そのデータを保持するため // に、このクラスからクラスを派生させる必要があります。 public override void Clear() { base.Clear(); OnChanged(EventArgs.Empty); } public override object this[int index] { set { base[index] = value; OnChanged(EventArgs.Empty); } } } } namespace TestEvents { using MyEventTest; class EventListener { private ListWithChangedEvent List; // イベントのフック // イベントの呼び出しの受け取りを開始するには、クライアントコードはまず、イベント // から呼び出されるメソッドを参照するイベント型のデリゲート(以下のコードで言うと、 // new ChangedEventHandler(ListChanged) )を作成する。 // 次に、+= を使用して、イベントに接続される他のデリゲートに、このデリゲートを結 // 合する。 public EventListener(ListWithChangedEvent list) { List = list; List.Changed += new ChangedEventHandler(ListChanged); } // イベントから呼び出されるメソッド。 private void ListChanged(object sender, EventArgs e) { Console.WriteLine("This is called when the event fires."); } // クライアントコードは、-= 演算子を使用してイベントからデリゲートを削除できる。 public void Detach() { List.Changed -= new ChangedEventHandler(ListChanged); List = null; } } // サンプルプログラムにもう一人 Listener を追加 class AnotherEventListener { private ListWithChangedEvent List; public AnotherEventListener(ListWithChangedEvent list) { List = list; List.Changed += new ChangedEventHandler(ListChanged); } private void ListChanged(object sender, EventArgs e) { Console.WriteLine("追加したもう一人の Listener に通知"); } public void Detach() { List.Changed -= new ChangedEventHandler(ListChanged); List = null; } } class Test { public static void Main() { ListWithChangedEvent list = new ListWithChangedEvent(); EventListener listener = new EventListener(list); AnotherEventListener anotherListener = new AnotherEventListener(list); list.Add("item 1"); list.Clear(); listener.Detach(); // += した順に関係なく、不要となったデリゲートを -= で削除できる list.Add("item 2"); list.Clear(); anotherListener.Detach(); } } } // C# 言語では任意のデリゲート型のイベントを使用できるが、.NET Framework ではイベントに使用で // きるデリゲート型に厳密なガイドラインがある。適正なデリゲート型の EventHandler が .NET // Framework によって既に定義されている。上記のサンプルで、イベントのデリゲート型を宣言を削除 // し、ChangedEventHandler を EventHandler と書き直せばよい。

参考になれば幸いです。

投稿2020/05/13 09:51

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

senkei_river

2020/05/14 11:09

ご回答ありがとうございます。内部的にはオブザーバパターンを使ってるのですね。書籍の紹介もありがとうございます。
Zuishin

2020/05/14 11:46

内部もなにも、それ以外の何に見えるんだろう。イベント作ったことないんだろうか。
gentaro

2020/05/14 11:50

内部ではないですね。イベントというのはオブザーバーパターンの実装そのものです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.47%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問