我在一个类中使用异步事件处理,该类每秒大约调用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调用的行为?