2012-03-08 98 views
4

有没有办法指定处理注册事件代表的顺序或优先级?例如,我有一个事件需要在任何其他事件之前立即处理,但我希望其他对象也可以注册事件的侦听器。这如何实现?事件优先级和流程订单

可以说,我想PROC1总是PROC之前这样做的运行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 

} 

的原因,我有一个是通过UDP流发送邮件的服务器。它会在突发数据前发送同步消息。我意识到这两个处理程序会在收到同步消息时触发,但为了减少延迟,我希望在dataProcessor事件之前处理syncProcessor对象事件。这将减少正在处理的同步消息的延迟。

另外,我的团队中的其他人也可能想要注册事件来处理特定的消息。他们可能有自己的对象来注册一个事件(可能不是MessageProcessor),即使同步消息应该尽可能的延迟。

编辑用更好的例子使目标更清晰。

+0

在处理程序中排队MessageEventArgs,然后启动一个实现优先级和依赖性的方法。这是你知道的一个bugfest,在我试图不经常失败之前,我会与自己进行激烈的对话。 – 2012-03-08 18:34:27

+0

我只是为了简单起见,因为我认识到在这种情况下注册同一资源/对象内的两个事件都是毫无意义的。我会更改我的设置以更准确地表示我的目标。 – galford13x 2012-03-08 18:34:58

+0

@Tony:有趣的想法。我同意这可能会进入一个问题领域。我实际上正在考虑创建一个接口,当有人注册一个事件时,DataClient会注册它,但有一个优先级映射对象,当收到一条消息时它会按照定义的顺序关闭处理程序中的事件。但这似乎也是一个不好的道路。 – galford13x 2012-03-08 18:37:46

回答

0

我要出去一个肢体,说不。 AFAIK事件本质上是异步调度的。所以会按照他们绑定的顺序发送。但结果可能会以不同的顺序返回。唯一的方法是在第一个事件的回调中派发第二个事件。这不是特定于语言的,更多的是关于事件的架构。

在你的例子中,因为调用是void,所以不要在proc1的末尾运行proc2?

+1

事件是异步调度的?我认为他们都是在同一个线程上发送的,当然这会让它们同步。我假定你的意思是他们没有按照定义的顺序发送?如果他们总是按照他们绑定的顺序发送,那么我可以通过确保首先注册最高优先级的事件来实现我的目标? – galford13x 2012-03-08 18:52:01

+0

所以你说整个线程在事件发送时睡觉?如果没有什么事情必然会发生。该应用程序将无限期地等待。这就是为什么我认为它在那个时候是异步的?没有? – 2012-03-08 23:36:57

+0

如果你需要它同步发生,你应该从函数1调用函数2,其中函数1是事件处理函数。否则,你将创造一个竞赛条件。这就是世界上每个其他事件模型的存在方式。我对它的工作方式有99%的肯定C# – 2012-03-08 23:40:31

1

在这种情况下,你最好只是要求在第一次活动结束的第二个事件,等等

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 2012-03-08 18:50:05