根据How do I make an eventhandler run asynchronously?中接受的答案:
class TestHarness
{
static void Main(string[] args)
{
var raiser = new SomeClass();
// Emulate some event listeners
raiser.SomeEvent += (sender, e) => { Console.WriteLine(" Received event"); };
raiser.SomeEvent += (sender, e) =>
{
// Bad listener!
Console.WriteLine(" Blocking event");
System.Threading.Thread.Sleep(5000);
Console.WriteLine(" Finished blocking event");
};
// Listener who throws an exception
raiser.SomeEvent += (sender, e) =>
{
Console.WriteLine(" Received event, time to die!");
throw new Exception();
};
// Raise the event, see the effects
raiser.DoSomething();
Console.ReadLine();
}
}
class SomeClass
{
public event EventHandler SomeEvent;
public void DoSomething()
{
OnSomeEvent();
}
private void OnSomeEvent()
{
if (SomeEvent != null)
{
var eventListeners = SomeEvent.GetInvocationList();
Console.WriteLine("Raising Event");
for (int index = 0; index < eventListeners.Count(); index++)
{
var methodToInvoke = (EventHandler)eventListeners[index];
methodToInvoke.BeginInvoke(this, EventArgs.Empty, EndAsyncEvent, null);
}
Console.WriteLine("Done Raising Event");
}
}
private void EndAsyncEvent(IAsyncResult iar)
{
var ar = (System.Runtime.Remoting.Messaging.AsyncResult)iar;
var invokedMethod = (EventHandler)ar.AsyncDelegate;
try
{
invokedMethod.EndInvoke(iar);
}
catch
{
// Handle any exceptions that were thrown by the invoked method
Console.WriteLine("An event listener went kaboom!");
}
}
}
如何确保每个委托的BeginInvoke一个接一个地调用?我的意思是,我想在不同的线程中处理事件的每个已注册的处理程序,但是每个对委托的BeginInvoke的调用应该在同一个线程上,这样它们就不会重叠。
据我所知,在一个新线程上调用BeginInvoke,即使它是被调用的同一个委托,因此可以并行调用委托,从而导致在事件处理程序中出现排序问题。
所有内容放在一起:如何异步调用所有代理,但每个代理按顺序调用?
背景是:某些事件处理程序可能需要“实时”的事件标记,有些会进行处理。实时事件处理程序不应该被其他处理程序减慢,并且事件标记的顺序必须按照它们发生时的正确顺序排列。