问题是:
我在一个类中使用异步事件处理,该类每秒调用事件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
-
这个
数据使用者
将其处理程序方法附加一次,并且在垃圾回收实例之前不会将其移除。
这是奇怪的部分;当我将调试器附加到处于中断状态的软件时,我可以看到
evt
OnDataReady()
引用
EventHandler
实例,不为空。它实际上叫BeginInvoke但是
HandleDataReady
方法从未输入。调试器显示
事件处理程序
基类的方法属性为空。我好像不明白为什么
事件处理程序
我最好的猜测是:
我的应用程序中完全不相关的东西是否会损坏
事件处理程序
? 我同时使用本机和托管c++库。
更新:
我最好的猜测是不太可能的,因为我已经运行了一些其他的测试,使我合理地确定本机库没有泄漏或损坏内存。
在用另一次日志记录再现问题之后,我可以看到事件并没有完全停止,而是以大约19小时的间隔被调用!显然,处理程序委托中有一个长时间运行的操作或阻塞。
为了确定这是我的代码而不是.NET,我有一个更新的问题。。。
第二个问题:
.NET(4.5)或其垃圾收集器中是否内置了可以阻止调用事件处理程序的行为?