事件和线程

时间:2012-12-26 13:50:09

标签: c# .net multithreading events event-handling

假设我有:

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

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

4 个答案:

答案 0 :(得分:2)

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

仔细考虑您希望应用程序的行为方式。简单地处理新线程上的每个数据包可能导致数据包无序处理。您可能希望将它们排队,然后让后台线程处理它们。或者你可能根本不需要做任何事情。

答案 1 :(得分:2)

你不应该假设。它可以是任何取决于按类型(ethernet_adapter对象)引发事件的方式。

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

如果是异步操作,将立即引发新事件。

答案 2 :(得分:0)

你可以在ThreadPool中排队整个任务,如下所示。

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

或者您可以为每个线程创建任务(.net 4.0)。

答案 3 :(得分:0)

据说你的ethernet_adapter课程中有一种方法:

protected virtual void OnPacketArrived(PacketArrivedEventArgs e)
{
    EventHandler<PacketArrivedEventArgs> handler = this.PacketArrived;

    if (handler != null)
    {
        handler(this, e);
    }
}

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

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