2012-03-08 7 views
4

登録されたイベントの代理人を処理する順序や優先度を指定する方法はありますか?たとえば、他のイベントの直前に処理したいイベントがありますが、他のオブジェクトにもイベントのリスナーを登録することができます。これはどのように達成できますか?イベントの優先度と処理の順序

は私がUDPストリームを介してメッセージを送信しているサーバーを持って、私はPROC1はいつもこれを行うために2

class MessageProcessor 
{ 
    private DataClient Client; 
    public MessageProcesser(DataClient dc) 
    { 
     Client = dc; 
     Client.MessageReceived += ProcessMessage; 
    } 

    void proc1(MessageEventArgs e) 
    { 
     // Process Message 
    } 

} 

class DataClient 
{ 
    public event MessageReceievedHandler MessageReceived; 
} 

void main() 
{ 
    DataClient dc = new DataClient(); 
    MessageProcessor syncProcessor = new MessageProcessor(dc); // This one is high priority and needs to process all sync immediately when they arrive before any data messages 
    MessageProcessor dataProcessor= new MessageProcessor(dc); // This one can process the data as it has time when sync messages are not being processed. 

    // do other stuff 

} 

procの前に理由を実行したいとしましょう。それはデータのバーストの前に同期メッセージを送信します。私は同期メッセージが受信されたときに両方のハンドラが起動することを知っていますが、latencyを減らすために、syncProcessorオブジェクトのイベントをdataProcessorイベントの前に処理したいと思います。これにより、処理中の同期メッセージの待ち時間が短縮されます。

さらに、私のチームの他の人が特定のメッセージを処理するためにイベントを登録することもできます。彼らはイベントを登録する独自のオブジェクトを持つかもしれません(MessageProcessorではないかもしれません)。でも、同期メッセージはできるだけ短い待ち時間を持つべきです。

EDITより良い例で目的をより明確にしました。

+0

ハンドラでMessageEventArgsをキューに入れ、次に優先度と依存性を実装するメソッドを開始します。これはあなたが知っている不幸なことです。私がこれをあまりにも頻繁に失敗させないようにする前に、私は自分と熱く話しています。 –

+0

この例では、同じリソース/オブジェクト内に両方のイベントを登録することが無意味であることを理解しているので、わかりやすくするために例を示しました。目標をより正確に表すためにセットアップを変更します。 – galford13x

+0

@トニー:興味深い考え。私はこれが問題の領域に入る可能性があることに同意します。私は実際には、誰かがイベントを登録したときに、DataClientがそれを登録するが、メッセージが受信されたときに定義された順序でハンドラのイベントを呼び出す優先度マッピングオブジェクトを持っているというインタフェースを作成しようと考えていました。しかし、これも下に行く悪い道のように思えました。 – galford13x

答えて

0

私は手足に出て、いいえと言います。 AFAIKのイベントは本質的にASNNCHRONOUSLYです。だから、彼らは縛られた順番で派遣されるでしょう。結果は異なる順序で返される可能性があります。唯一の方法は、最初のイベントのコールバック内に2番目のイベントを送出することです。これは言語特有のものではなく、イベントのアーキテクチャに関するものです。

この例では、呼び出しが無効なので、proc1の最後にproc2を実行しないでください。

+1

イベントは非同期でディスパッチされますか?私は彼らがすべて同じスレッドに派遣されていると思っていました。私は彼らが定義された順序で派遣されているということを意味すると思いますか?彼らが縛られた順番で常に派遣されれば、最も優先度の高い出来事が最初に登録されることを保証することによって私は目標を達成することができます。 – galford13x

+0

イベントがディスパッチされたときにスレッド全体がスリープ状態になるというあなたの意見は?何もイベントに縛られていない場合はどうなりますか?アプリは無期限に待つだろう。だから私はその時点で非同期だと思うのはなぜですか?いいえ? –

+0

同期が必要な場合は、関数1が関数1をイベントハンドラとして呼び出す必要があります。それ以外の場合は、競合状態を作成します。これは世界のあらゆる他のイベントモデルがどのように存在するかです。私はそれがC言語でどのように動作するのか99%肯定的です# –

1

この場合、あなたはなど、単に最初のイベントの終わりに2番目のイベントを呼び出したほうが良いです

0

これはあなたが定義した独自のイベントであれば、あなたの最善の策は、それを拡張するかもしれませんBeforeMessageReceived、MessageReceived、およびAfterMessageReceivedイベントを持ちます。 (メッセージが受信される前にの前にを知ることができるので、大丈夫です。多分MessageProcessedがより良いルートになるでしょう)。

これにより、異なるイベントハンドラがどこに発生するかをより正確に制御できます。

あなたはイベントはあちこちパッテン後、前に、同じを参照してください。

5

イベントに複数回サブスクライブすると、イベントが発生したときにハンドラの実行順序を確認する方法がありません。

this answerによると、サブスクリプションオーダーの注文ですが、ポスト作者が言ったように、実装の詳細であり、あなたはそれに頼るべきではありません。

ハンドラーを既知の順序で実行する独自の「イベントマネージャー」(下記の汚れた例を参照)を書くこともできますが、それは良い考えではないと思います。たぶん、イベントを再設計して要件を削除する必要があります。

public class MyClass 
{  
    // Could be anything... 
    public delegate void MyEventHandler(object sender, EventArgs e); 

    public event MyEventHandler TestEvent; 

    public void Test() 
    { 
     if (this.TestEvent != null) 
     { 
      this.TestEvent(this, EventArgs.Empty); 
     } 
    } 
} 

public class EventManager 
{ 
    private List<EventHandler> Handlers = new List<EventHandler>(); 

    public void AddHandler(EventHandler handler) 
    { 
     this.Handlers.Add(handler); 
    } 

    public void RemoveHandler(EventHandler handler) 
    { 
     this.Handlers.Remove(handler); 
    } 

    public void Handler(object sender, EventArgs e) 
    { 
     foreach (var z in this.Handlers) 
     { 
      z.Invoke(sender, e); 
     } 
    } 
} 

private static void Main(string[] args) 
{ 
    MyClass test = new MyClass(); 

    EventManager eventManager = new EventManager(); 

    // Subscribes to the event 
    test.TestEvent += eventManager.Handler; 

    // Adds two handlers in a known order 
    eventManager.AddHandler(Handler1); 
    eventManager.AddHandler(Handler2); 

    test.Test(); 

    Console.ReadKey(); 
} 

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

private static void Handler2(object sender, EventArgs e) 
{ 
    Console.WriteLine("2"); 
} 
+0

+1:この例は私がやろうとしていたものと似ています。しかし、私はあまりにも下に行く悪い道だと思った。私は.netに組み込まれたソリューションを目指していました。 – galford13x

関連する問題