事件和线程

本文关键字:线程 事件 | 更新日期: 2023-09-27 17:49:30

假设我有:

ethernet_adapter.PacketArrived += (s, e) => 
{
    //long processing...
};

处理可能需要很长时间,当它在中间时,另一个数据包已经到达。接下来会发生什么:处理完成,然后触发另一个事件,或者可能立即在新线程上触发新事件?

事件和线程

你不应该假设。它可以是任何东西,这取决于事件是如何通过类型(ethernet_adapter对象)引发的。

如果是同步操作,则在当前操作进行之前不会引发新事件。

如果是异步操作,则立即引发新的事件

很可能这是一个同步操作。它将在另一个线程上发生的唯一方式是,引发事件的对象在另一个线程上发生,或者在处理程序中发生。有许多方法可以做到这一点,但如果使用。net 4,通常更倾向于使用System.Threading.Tasks.Task

仔细考虑您希望应用程序如何表现。简单地在一个新线程上处理每个数据包可能会导致数据包被乱序处理。你可能想把它们排队,然后让一个后台线程处理它们。或者您可能根本不需要做任何事情。

假设在您的ethernet_adapter类中有一个方法:

protected virtual void OnPacketArrived(PacketArrivedEventArgs e)
{
    EventHandler<PacketArrivedEventArgs> handler = this.PacketArrived;
    if (handler != null)
    {
        handler(this, e);
    }
}

长时间处理同步订阅者(如在您的示例中)将阻止对所有订阅者的内部枚举。但是!如果ethernet_adapter每次在不同的线程上调用它,它可能不会阻塞对OnPacketArrived的后续调用-因此您将获得两个并发的长处理,等等。

作为一个例子,看看Socket的实现:它的异步方法导致IOCP线程上调用完成回调-每次都不同,而在IO ThreadPool中有任何。

你可以在ThreadPool中排队,如下所示:

ethernet_adapter.PacketArrived += (s, e) => 
{
ThreadPool.QueueUserWorkItem("long processing item");
};

或者你可以为每个线程创建task(.net 4.0)