是什么导致该事件停止被调用?

时间:2019-02-15 16:22:33

标签: c# events .net-4.5 eventhandler

问题:

我在一个类中使用异步事件处理,该类每秒大约调用60次事件。如果我将软件运行了几个小时,我发现它最终会进入一种状态,即事件停止调用分配的委托,而不会看到任何异常或用户输入。

这是我正在使用的事件代码的简化版本:

class DataSource
{
    public event EventHandler<DataReadyEventArgs> DataReady;

    private void OnDataReady()
    {
        EventHandler<DataReadyEventArgs> evt = DataReady;
        if (evt != null)
        {
            Trace.WriteLine("Invoking DataReady...");
            DataReadyEventArgs args = new DataReadyEventArgs();
            evt.BeginInvoke(this, args, new AsyncCallback(DataReadyHandled), null);
        }
    }

    private void DataReadyHandled(IAsyncResult result)
    {
        AsyncResult aresult = result as AsyncResult;
        EventHandler<DataReadyEventArgs> evt = aresult.AsyncDelegate as EventHandler<DataReadyEventArgs>;
        if (evt != null)
        {
            try
            {
                evt.EndInvoke(result);
                Trace.WriteLine("DataReady was handled.");
            }
            catch
            { }
        }
    }
}

class DataConsumer
{
    public DataConsumer(DataSource src)
    {
        src.DataReady += HandleDataReady;
    }

    public void HandleDataReady(object sender, DataReadyEventArgs e)
    {
        Trace.WriteLine("Handling DataReady");
    }
}

为避免写出进一步的代码以全面了解情况,您还可以进行以下假设:

  • 总是强烈引用DataSource实例,因此在DataConsumer遇到事件时不会对其进行垃圾回收
  • DataConsumer一次附加其处理程序方法,直到实例被垃圾回收后才将其删除。

这是奇怪的部分;当我将调试器附加到处于故障状态的软件时,可以看到evt中的OnDataReady()变量引用了一个EventHandler实例,并且不为null。它实际上调用了BeginInvoke,但从未输入HandleDataReady方法。调试器显示EventHandler基类的Method属性为null。我似乎无法弄清楚EventHandler可能如何被更改。

(第一个)问题:

运行几个小时后,导致上述代码中的事件停止调用的原因是什么?

我的最佳猜测:

我的应用程序中完全不相关的内容会破坏EventHandler的内存吗?我正在使用本机和托管c ++库。


更新:

最好的猜测似乎是不可能的,因为我运行了其他一些测试,这些测试使我有理由确保本机库不会泄漏或破坏内存。

在再次使用日志记录再现问题之后,我可以看到该事件并未完全停止,而是在大约19小时的间隔内被调用!显然,在处理程序委托中的某处存在长时间运行的操作或阻塞。

为了确定这是我的代码而不是.NET,我有一个更新的问题...

(第二个)问题

.NET(4.5)或其垃圾收集器是否内置任何可阻止EventHandler调用的行为?

0 个答案:

没有答案