c# - 如果我调用 C# 事件处理程序并调用它,会发生什么情况?

标签 c# .net events thread-safety

这个问题是对 C# Events and Thread Safety 的跟进问题(我不是那个问题的作者)和 Eric Lippert 的相关博客文章 Events and Races . SO 上还有其他类似的问题,但实际上没有一个考虑这种情况,普遍的共识是只要你退订就安全,但我不相信这一直都是真的。

根据 SO 问题和博客中的讨论,应该使用的模式类似于:

var ev = NotifyPropertyChanged;
if (ev != null)
    ev(this, new PropertyChangedEventArgs("Foo"));

但是如果出现以下情况怎么办:
1) 我订阅了一个监听器:

mytype.NotifyPropertyChanged += Handler; // Handler is instance method in SomeObject class

2) 我(或运行时,由于作用域)处理包含监听器的 SomeObject 并取消订阅监听器,大约在属性通知发生的同时。

3) 虽然由于时间很短而不太可能发生这种情况,但理论上可能是因为 ev 保留了不再存在的旧订阅者,它将调用一个函数不再存在的对象。

根据 Eric Lippert 的说法,“事件处理程序需要在面对被调用时保持健壮,即使在事件已取消订阅后也是如此”。但是如果处理程序被和处理取消订阅,它就不能再处理调用。处理这种情况的正确方法是什么?

将 (1) 中的代码包装在 try-catch 中?应该捕获什么异常? ObjectDisposedException 似乎有可能发生,但我认为这不是唯一可能发生的情况。

最佳答案

我相信您的意思是说一个对象已经被 GC 处理过,但没有被释放。那不可能发生; MultiCastDelegate(EventHandler)通过其订阅的方法维护对该对象的引用,即,在删除处理程序之前,它不能被 GC。


Dispose() 与方法不可用无关,它是一种用于清理 native 资源的模式,即 GC 无法处理的资源。

对象本身仍然存在并且很好,但如果您调用依赖于该本地资源的方法(当然取决于实现。关键是该对象和方法一样仍然存在),它可能会抛出异常。

当您调用 Dispose() 时,没有什么神奇的事情发生。我可以轻松地创建一个实现 IDisposable 并且具有完全空的 Dispose() 方法的类。随心所欲地调用它,它什么都不做,也不会以任何方式改变对象的状态。

关于c# - 如果我调用 C# 事件处理程序并调用它,会发生什么情况?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8333448/

相关文章:

c# - 在 windows phone 7 模拟器上模拟连接不稳定进行测试

c# - 使用 OpenXML 合并 PowerPoint 幻灯片

c# - 如何在 WPF 中实现圆锥形/圆锥形/圆形渐变

.net - 为 .NET 跨平台开发组织 Visual Studio 项目和代码的行业标准方法是什么

c# - IoC Container Unity 搞乱了我

c# 将类作为参数传递

c# - azure函数未将异常记录到应用程序洞察中

c# - 何时强制执行 LINQ 查询评估?

events - 在 f# 中创建 Event.create?

javascript - 如何让鼠标滚轮事件在 jQuery 中只触发一次?