none
登録したイベントハンドラが処理される順番 RRS feed

  • 質問

  • 次の様に、イベントハンドラを登録した場合、

     

    button.Click += new EventHandler(button_Click1);
    button.Click += new EventHandler(button_Click2);

    button_Click1、button_Click2 の順にハンドラは処理(コール)されるものなのでしょうか。

     

    テストしてみてた結果では「+=」で登録した順にコールされているたいなのですが、

    仕様的にも「登録した順にコールされる」となっているのでしょうか?

     

    もし、「登録した順にコールされる」のであれば、この登録された順番を変えたり、

    既に登録されているイベントハンドラに、INSERT的な感じで、ハンドラの登録を

    割り込ませたりって可能なのでしょうか?

     

    button.Click += new EventHandler(button_Click1);
    button.Click += new EventHandler(button_Click2);
    // ここで何とか処理して、button_Click0 のハンドラを button_Click1 の前に割り込ましたい

     

    この結果、buttonクリックで、 button_Click0、button_Click1、button_Click2 の順に

    ハンドラがコールされる様にさせるのが理想なのですが。

     

    こんな事って可能でしょうか?

     

    皆様、ご教授願えますでしょうか。

    宜しくお願い致します。

     

    2007年9月4日 5:34

すべての返信

  • 順番は全く保証されていません。
    イベントは独自に実装できるので、登録されたハンドラをどの順番で実行しようと自由です。

     

    2007年9月4日 5:51
  • http://www.microsoft.com/japan/msdn/community/gdn/ShowPost-38995.htm
    このあたりが参考になりますか?
     
    ・汎用的には無理
    ・対象を特定する場合、十分な権限があれば可能
     
    といったところです。
     
    2007年9月4日 22:06
  • 囚人さん、K.Takaokaさん、回答ありがとうございます。

     

    >http://www.microsoft.com/japan/msdn/community/gdn/ShowPost-38995.htm

    紹介して頂いたページでは、「イベントハンドラは登録した順に実行される」と解釈できる

    のですが。私の解釈(読解)の仕方が間違っているのでしょうか?

     

    >・汎用的には無理
    「汎用」とは「全ての言語で」という事でしょうか?
     
    >・対象を特定する場合、十分な権限があれば可能
    「対象」とは言語を指すのでしょうか?
    「権限」って何の権限?
     
    2007年9月6日 3:46
  • C# において、

    ・Delegate に対する += 演算は、順番が言語仕様で保証されています。

    ・add/remove 節を使わずに宣言した event は、順番が言語仕様で保証されています。

    それ以外は実装依存です。

     

    以上のことは言っていませんね。

     

    event の add/remove は自前で好きに実装することも可能なので、add されたときに無視するとかできますし、Delegate.Combine を既存のと追加されたのとを通常と逆の順で呼び出すこともできますし。

    2007年9月6日 4:20
  • 「マルチキャストデリゲートは呼び出し順が保証されているだろう」という話です。イベントはまた違います。
    イベントはクラスが独自に実装できます。そして外部からは、イベントをどう実装しているのかを意識できません(してはいけません)。
    以下は、イベントハンドラを登録した順とは逆に実行される例です。


    Code Snippet

    using System;

    public delegate void StackEventHandler(object sender, EventArgs e);

    class Hoge
    {
     System.Collections.Stack _stackEvent = new System.Collections.Stack();

     public event StackEventHandler StackEvent
     {
      add
      {
       _stackEvent.Push(value);
      }
      remove
      {
       // 削除は不可!
      }
     }

     public void Run()
     {
      while(_stackEvent.Count != 0)
      {
       StackEventHandler h = (StackEventHandler)_stackEvent.Pop();
       h(this, EventArgs.Empty);
      }
     }
    }

    class Class1
    {
     static void Main(string[] args)
     {
      Hoge h = new Hoge();
      h.StackEvent += new StackEventHandler(h_StackEvent1);
      h.StackEvent += new StackEventHandler(h_StackEvent2);
      h.Run();
     }

     private static void h_StackEvent1(object sender, EventArgs e)
     {
      Console.WriteLine("No 1");
     }

     private static void h_StackEvent2(object sender, EventArgs e)
     {
      Console.WriteLine("No 2");
     }
    }

     

     

     

    2007年9月6日 4:21
  • 本題については他の方々が答えられておりますので、簡単な解決策をひとつ。

    ArrayList 等を使った独自のメソッド リストを作り、

    単一のイベント ハンドラから逐次呼び出すという方式ではどうでしょう。

    2007年9月6日 5:20
  •  ぶるーの さんからの引用

    私の解釈(読解)の仕方が間違っているのでしょうか?

     
    この点に関してはすでに他の方がかかれている通りで、解釈が微妙に間違っています。

     

     ぶるーの さんからの引用
    >・汎用的には無理
    「汎用」とは「全ての言語で」という事でしょうか?
     
    .NET では、プログラム言語に依存して技術的な問題が発生することは非常に稀です。
    次の、
     
    >・対象を特定する場合、十分な権限があれば可能
     
    という内容とあわせて「対象を特定しない」という意味です。
     
    対象というのは、話題にあがっている「特定のイベントに、最初に実行したいイベントハンドラを挿入する」という行為に対する返答ですので、対象を特定するというのは、「System.Windows.Forms.Button の Click イベント」などというイベントの限定をさしています。
    それに対して「汎用的には不可能」というのは、「すべてのコントロールの」とか「XXX クラスのすべてのイベント」などという汎用化が可能な実装は非常に困難であるか不可能である、ということです。
     
    前述の URL のほうを見てもらえばわかるかもしれませんが、このような対象の特定を行う場合には、その実装にたいする理解や試行錯誤が多少あれば、どのような手段を用いてイベントハンドラが管理されているかを特定することが可能です。
    あとは、リフレクション等を利用することでそのイベントハンドラの管理部分を変更してやることで、イベントから呼び出されるイベントハンドラの順序を操作することが可能になるものは多くあります。
    一般的なコントロール類の実装では、イベントハンドラの管理部分は private などのアクセス制御を設定されており、外部から修正がきかないようになっていますので、それを無理やり変更するためには、ある程度の実行権限が必要です。(どのような操作にどのような権限が必要であるかは、MSDN などのドキュメントに記載されているはずです)
    2007年9月7日 15:19