假设我有:
ethernet_adapter.PacketArrived += (s, e) =>
{
//long processing...
};
处理可能需要很长时间,当它在中间时,另一个数据包已经到达。接下来会发生什么:处理完成,然后触发另一个事件,或者可能立即触发新事件但在新线程上?
假设我有:
ethernet_adapter.PacketArrived += (s, e) =>
{
//long processing...
};
处理可能需要很长时间,当它在中间时,另一个数据包已经到达。接下来会发生什么:处理完成,然后触发另一个事件,或者可能立即触发新事件但在新线程上?
很有可能这是一个同步操作。它发生在另一个线程上的唯一方法是如果引发事件的对象在另一个线程上这样做,或者如果你在处理程序中这样做。有很多方法可以做到这一点,但System.Threading.Tasks.Task
如果使用 .NET 4,通常会首选使用。
仔细考虑您希望应用程序的行为方式。简单地在新线程上处理每个数据包可能会导致数据包被无序处理。您可能希望将它们排队并在此时让后台线程处理它们。或者你可能根本不需要做任何事情。
你不应该假设。它可以是任何东西,具体取决于(ethernet_adapter
对象)类型如何引发事件。
如果是同步操作,则在当前操作正在进行之前不会引发新事件。
如果是异步操作,则立即引发新事件。
您可以按如下方式在 ThreadPool 中排队整个任务。
ethernet_adapter.PacketArrived += (s, e) =>
{
ThreadPool.QueueUserWorkItem("long processing item");
};
或者您可以为每个线程创建任务(.net 4.0)。
假设您的类中有一个方法ethernet_adapter
:
protected virtual void OnPacketArrived(PacketArrivedEventArgs e)
{
EventHandler<PacketArrivedEventArgs> handler = this.PacketArrived;
if (handler != null)
{
handler(this, e);
}
}
长时间处理同步订阅者(如您的示例)将阻止所有订阅者的内部枚举。但!它可能不会阻止对OnPacketArrived
ifethernet_adapter
每次在不同线程上调用它的后续调用 - 因此您将获得两个并发的长处理,依此类推。
作为一个例子,看一下Socket
实现:它的异步方法导致在 IOCP 线程上调用完成回调 - 每次都有不同的 IO ThreadPool
。