繁体   English   中英

EventHandler订户中保证的处理顺序

[英]Guaranteed order of processing in EventHandler subscriber

我有一个异步调用(使用BeginInvoke / EndInvoke)的EventHandler。

提供的EventArgs包含一个递增值。

活动连续多次被提出; 依次引发事件,以使它们的EventArgs值对于每个后续调用递增。

在订阅服务器中,我试图按引发它们的顺序处理这些事件,并且在订阅服务器中有一个锁,以确保我只能同时处理一个事件,但是,我有一个问题,即锁并不总是在订单被要求,导致事件被无序处理。

我在这里看到: lock()是否保证按请求的顺序获取? 这在一定程度上是可以预期的; 也就是说,我不能依赖于按请求顺序进行的锁定。

该问题的答案之一将我定向到了这里的排队锁实现: 是否有一个同步类保证C#中的FIFO顺序?

在走那条路之前,我有三个问题:

  1. 如果(迅速)引发多个事件,是否总是按照引发事件的顺序调用订户的处理程序?
  2. 如果我实现了如上所述的排队锁,是否可以依靠以正确顺序调用Enter()方法? (即,即使“事件1”之后触发了“事件2”,仍然存在“事件2”将在“事件1”之前到达我的订户中的queuedLock.Enter()的风险);
  3. 鉴于EventHandler需要异步(以防止订阅者阻塞线程),使用EventHandler做到这一点是不可能/合理的吗,我是否需要实现某种单独的异步事件队列?

如果(迅速)引发多个事件,是否总是按照引发事件的顺序调用订户的处理程序?

否。首先,对BeginInvoke的每次调用都会将工作项排队到线程池中。 每个工作项在不同的线程上执行,并且这些线程处于竞争状态。 其次,即使您的订户以正确的顺序被调用,这些调用仍然处于竞争状态; 并且,如果您在订户内部进行了锁定,则未定义授予锁定的顺序。

如果我实现了如上所述的排队锁,是否可以依靠以正确顺序调用Enter()方法? (即,即使“事件1”之后触发了“事件2”,仍然存在“事件2”将在“事件1”之前到达我的订户中的queuedLock.Enter()的风险);

不,出于上述相同的原因。

鉴于EventHandler需要异步(以防止订阅者阻塞线程),使用EventHandler做到这一点是不可能/合理的吗,我是否需要实现某种单独的异步事件队列?

是。 由于必须按顺序处理事件,因此与多线程相比,首选使用队列。 产生多个线程只是为了让它们全部等待获取单个锁没有意义。

使用队列

使用队列时,生产者仅使事件入队而不会阻塞。 在消费者方面,只有一个线程可以逐个出队和处理事件。 这是每个事件调用订户的线程。 请注意,队列为空时,使用者线程将被阻塞。

您仍然可以并行处理

例如,如果一个事件属于(例如)一个客户,并且必须按顺序处理来自同一客户的事件,而来自两个不同客户的两个事件则可以独立处理。

在这种情况下,您可以将属于不同客户的事件分成多个队列,并且每个队列有一个单独的使用者线程。 为此,您必须确保来自同一客户的事件被映射到同一队列。

例如,如果您有N个队列,则可以通过计算以N为模的hash(Customer)将事件映射到队列。

现有的生产者-消费者队列

.NET开箱即用提供了两个专用队列:

您还可以看一下:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM