将事件分配给事件处理程序的两种不同类型之间的区别

2024-04-08

我在 SO 中看到了这个示例代码,它说一种做法不好,另一种做法很好。但我不明白为什么? 事实上,我收到了著名的 RCW COM 对象错误,该帖子说这可能是一个原因。

public class SomeClass
{
    private Interop.ComObjectWrapper comObject;
    private event ComEventHandler comEventHandler;

    public SomeClass()
    {
        comObject = new Interop.ComObjectWrapper();

        // NO - BAD!
        comObject.SomeEvent += new ComEventHandler(EventCallback);

        // YES - GOOD!
        comEventHandler = new ComEventHandler(EventCallback);
        comObject.SomeEvent += comEventHandler
    }

    public void EventCallback()
    {
        // DO WORK
    }

}

编辑:这是来源的链接:无法使用已与其底层 RCW 分离的 COM 对象 https://stackoverflow.com/questions/1567017/com-object-that-has-been-separated-from-its-underlying-rcw-cannot-be-used


我认为这两个代码片段是相同的,我们在这里没有任何强/弱引用的问题。

背景

首先,如果我们的Interop.ComObjectWrapper提供 CLR 事件(即在委托中存储事件处理程序的事件),我们肯定会从ComObjectWrapper到我们的对象。

任何委托都包含两部分:Target类型的object以及指向特定方法的方法指针。如果Target is null比回调指向静态方法。

不可能有一个代表Target类型的弱引用 http://msdn.microsoft.com/en-us/library/system.weakreference.aspx。有所谓的弱事件模式 http://msdn.microsoft.com/en-us/library/aa970850.aspx但它是在之上实现的事件管理器 http://msdn.microsoft.com/en-us/library/hh199438.aspx而不是普通的代表。

在现场存储事件处理程序不会有帮助。第1部分

内部事件实现是指订阅事件后:

comObject.SomeEvent += EventCallback;

comObject对象隐式地持有对SomeClass目的。无论您使用哪种订阅技术,这都是事实以及 ComObject 是否是 COM 对象包装器。

订阅事件会在生命周期方面添加两个对象之间的隐式依赖关系。这就是 .NET 世界中最常见的内存泄漏是由订阅长寿命对象的事件引起的。事件订阅者不会死亡,直到应用程序中可访问事件持有者。

在现场存储事件处理程序不会有帮助。第2部分

但是如果我的假设不正确并且ComObjectWrapper提供了一些弱事件模式的概念,将事件处理程序保存在字段中不会有任何帮助。

让我们回顾一下事件关键字的含义:

private event ComEventHandler comEventHandler;
... 
comEventHandler = new ComEventHandler(EventCallback);

在当前字段中保存回调(基本上我们可以将私有事件视为简单的委托字段)不会改变现有行为。

我们已经知道委托是一个简单的对象,它存储对目标对象的引用(即SomeClass对象)和方法(即public void EventCallBack())。这意味着在字段中存储额外的委托会添加对SomeClass来自SomeClass itself.

基本上,在字段中存储事件处理程序在语义上等同于在 SomeClass 中存储附加引用:

私有 SomeClass someClass;

公共 SomeClaas() { // 这与存储委托基本相同 // 在 comEventHandler 字段中 一些类=这个; }

在中存储强引用SomeClass不会延长当前对象的生命周期。这意味着如果ComObjectWrapper不会对SomeClass存储事件处理程序的对象comEventHandler不会延长 SomeClass 的生命周期,也不会阻止SomeClass来自垃圾收集。

结论

将事件处理程序存储在私有字段中不会延长对象的生命周期,也不会阻止它进行垃圾回收。

这就是为什么以下代码片段在对象生命周期方面没有区别:

    // GOOD!
    comObject.SomeEvent += new ComEventHandler(EventCallback);

    // EVEN BETTER!
    comObject.SomeEvent += EventCallback;

    // NOT GOOD, BECAUSE WAN'T HELP!
    comEventHandler = new ComEventHandler(EventCallback);
    comObject.SomeEvent += comEventHandler
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将事件分配给事件处理程序的两种不同类型之间的区别 的相关文章

  • 在一个数据访问层中处理多个连接字符串

    我有一个有趣的困境 我目前有一个数据访问层 它必须与多个域一起使用 并且每个域都有多个数据库存储库 具体取决于所调用的存储过程 目前 我只需使用 SWITCH 语句来确定应用程序正在运行的计算机 并从 Web config 返回适当的连接字
  • 通过引用传递 [C++]、[Qt]

    我写了这样的东西 class Storage public Storage QString key const int value const void add item QString int private QMap
  • 如何在 Cassandra 中存储无符号整数?

    我通过 Datastax 驱动程序在 Cassandra 中存储一些数据 并且需要存储无符号 16 位和 32 位整数 对于无符号 16 位整数 我可以轻松地将它们存储为有符号 32 位整数 并根据需要进行转换 然而 对于无符号 64 位整
  • C++11 删除重写方法

    Preface 这是一个关于最佳实践的问题 涉及 C 11 中引入的删除运算符的新含义 当应用于覆盖继承父类的虚拟方法的子类时 背景 根据标准 引用的第一个用例是明确禁止调用某些类型的函数 否则转换将是隐式的 例如最新版本第 8 4 3 节
  • std::vector 与 std::stack

    有什么区别std vector and std stack 显然 向量可以删除集合中的项目 尽管比列表慢得多 而堆栈被构建为仅后进先出的集合 然而 堆栈对于最终物品操作是否更快 它是链表还是动态重新分配的数组 我找不到关于堆栈的太多信息 但
  • 随着时间的推移,添加到 List 变得非常慢

    我正在解析一个大约有 1000 行的 html 表 我从一个字符串中添加 10 个字符串 td 每行到一个list td
  • 如何在 C# 中打开 Internet Explorer 属性窗口

    我正在开发一个 Windows 应用程序 我必须向用户提供一种通过打开 IE 设置窗口来更改代理设置的方法 Google Chrome 使用相同的方法 当您尝试更改 Chrome 中的代理设置时 它将打开 Internet Explorer
  • ASP.NET Core 3.1登录后如何获取用户信息

    我试图在登录 ASP NET Core 3 1 后获取用户信息 如姓名 电子邮件 id 等信息 这是我在登录操作中的代码 var claims new List
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • 在 Unity 中实现 Fur with Shells 技术

    我正在尝试在 Unity 中实现皮毛贝壳技术 http developer download nvidia com SDK 10 5 direct3d Source Fur doc FurShellsAndFins pdf Fins 技术被
  • LINQ:使用 INNER JOIN、Group 和 SUM

    我正在尝试使用 LINQ 执行以下 SQL 最接近的是执行交叉联接和总和计算 我知道必须有更好的方法来编写它 所以我向堆栈团队寻求帮助 SELECT T1 Column1 T1 Column2 SUM T3 Column1 AS Amoun
  • 为什么使用小于 32 位的整数?

    我总是喜欢使用最小尺寸的变量 这样效果就很好 但是如果我使用短字节整数而不是整数 并且内存是 32 位字可寻址 这真的会给我带来好处吗 编译器是否会做一些事情来增强内存使用 对于局部变量 它可能没有多大意义 但是在具有数千甚至数百万项的结构
  • C 函数 time() 如何处理秒的小数部分?

    The time 函数将返回自 1970 年以来的秒数 我想知道它如何对返回的秒数进行舍入 例如 对于100 4s 它会返回100还是101 有明确的定义吗 ISO C标准没有说太多 它只说time 回报 该实现对当前日历时间的最佳近似 结
  • 在 WPF 中使用 ReactiveUI 提供长时间运行命令反馈的正确方法

    我有一个 C WPF NET 4 5 应用程序 用户将用它来打开某些文件 然后 应用程序将经历很多动作 读取文件 通过许多插件和解析器传递它 这些文件可能相当大 gt 100MB 因此这可能需要一段时间 我想让用户了解 UI 中发生的情况
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • 使用特定参数从 SQL 数据库填充组合框

    我在使用参数从 sql server 获取特定值时遇到问题 任何人都可以解释一下为什么它在 winfom 上工作但在 wpf 上不起作用以及我如何修复它 我的代码 private void UpdateItems COMBOBOX1 Ite
  • 对于某些 PDF 文件,LoadIFilter() 返回 -2147467259

    我正在尝试使用 Adob e IFilter 搜索 PDF 文件 我的代码是用 C 编写的 我使用 p invoke 来获取 IFilter 的实例 DllImport query dll SetLastError true CharSet
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • C# 使用“?” if else 语句设置值这叫什么

    嘿 我刚刚看到以下声明 return name null name NA 我只是想知道这在 NET 中叫什么 是吗 代表即然后执行此操作 这是一个俗称的 条件运算符 三元运算符 http en wikipedia org wiki Tern
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat

随机推荐

  • .HTACCESS 文件导致内部服务器错误

    我已经复制了文件和数据库BradPPresents com http BradPPresents com to BradP com http BradP com 由于 joomla 启用了 漂亮 URL 因此需要 htaccess 文件才能
  • 占位符中有两种不同的文本样式

    输入框占位符可以有两种样式吗 这是我正在寻找的示例 https i stack imgur com 7OH9A png https i stack imgur com 7OH9A png 选项是使用包含文本的背景图像 或者使用与文本重叠的元
  • NLTK 中的 FreqDist 未对输出进行排序

    我是 Python 新手 我正在尝试自学语言处理 python 中的 NLTK 有一个名为 FreqDist 的函数 可以给出文本中单词的频率 但由于某种原因它无法正常工作 这是教程让我写的 fdist1 FreqDist text1 vo
  • Hadoop 分布式缓存类路径

    我有一个 Hadoop 0 20 2 集群 我正在考虑使用分布式缓存 http hadoop apache org common docs r0 20 2 api org apache hadoop filecache Distribute
  • 如何摆脱 NSLog 中的所有这些垃圾?

    当我使用 NSLog fooBar 它打印出很多我不想要的东西 2009 09 03 13 46 34 531 MyApp 3703 20b fooBar 有没有办法在没有这个大前缀的情况下将某些内容打印到控制台 我想在控制台中绘制一张桌子
  • 在 Eclipse 中的两个独立设备上运行调试

    我有 2 台 Android 设备连接到我的电脑 我需要同时调试它们 因为我在它们之间来回发送数据 当我将它们都设置为调试模式时 它一次只会停止一个 我无法在发送后立即停止 发送者 然后调试 接收者 它只是不喜欢而已 我真的需要能够运行两个
  • 没有错误:未调用 PDO 构造函数

    下午好 我昨天开始使用 PDO 但遇到了一些问题 我正在创建扩展类 它不起作用 而且我找不到错误 这是我的助手类的代码 用于工作女巫 PDO class EPDO extends PDO Some identificator of conn
  • 如何在 Javascript 的脚本元素中添加局部变量和不同的函数[关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我需要创建一个脚本元素 如下所示 div class abcd div 我尝试通过首先通过 document Createelement 选
  • 如何查找特定

    环境 美丽的汤4 Python 2 7 5 Logic 找到所有 li 内的实例 ul 与一类my class eg ul class my class li thing one li li thing two li ul 澄清 只需获取之
  • Flutter - 自动调整 AlertDialog 大小以适合列表内容

    我需要从休息网络服务动态加载列表城市 并让用户从警报对话框中选择一个城市 我的代码 createDialog fetchCities then response showDialog context context builder Buil
  • VSCode 显示文件夹 /run/user/1000/doc 中路径的问题

    我最近在更新到 v1 77 3 后在 VSCode 中遇到了一个问题 新项目的路径是错误的 而旧项目的路径是正确的 特别是 新项目在前缀为的文件夹中打开 run user 100 doc 接下来是类似于 sha256 的摘要 每个文件夹都不
  • \ 对非转义字符有何作用?

    I 又问了一个不好的问题 https stackoverflow com questions 4380386 fix escape javascript escape character所以我会问别的事情 根据http www c poin
  • 存储值以便在以后的函数中使用的最佳方法是什么?我听说全局变量很邪恶

    所以我使用的代码位于http jsfiddle net 8j947 10 http jsfiddle net 8j947 10 它为变量 isLive 返回 true 或 false 值 如何在稍后的函数中使用变量 onLive 我在以下位
  • 使用Jackson写yaml?

    我正在使用 Jackson 来读取和修改 yaml 文件 效果很好 不过 我找不到编写 yaml 所需的魔法 ObjectMapper mapper new ObjectMapper new YAMLFactory ObjectNode r
  • 使用 docker-compose 时如何为 mongodb 镜像添加 --auth ?

    我正在使用 docker compose 来运行由 node mongodb nginx 创建的项目 我已经使用构建了该项目docker build 然后我用docker up d nginx开始我的项目 但我还没有找到使用 auth 运行
  • 我应该在 Common Lisp 中使用哪些正则表达式库? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • Python 列表索引效率

    关于内置 python 列表对象的快速问题 假设您有一个包含数字 0 99 的列表 您正在编写一个程序 该程序获取列表中的最后一项并将其用于其他目的 使用list 1 比使用list 99 更有效吗 换句话说 无论哪种情况 python 都
  • Python-从另一个列表中删除一组列表

    array1 1 2 3 4 5 6 7 8 9 array2 1 2 2 2 5 6 6 6 9 temp set array2 array1 remove temp Traceback most recent call last Fil
  • JqG​​rid 搜索字段的多个文本框

    我想知道 JqGrid 高级搜索是否可以为我想要搜索的某些字段显示多个文本框 例如 如果我有一个 电话号码 字段 我希望能够可视化 2 个框 一个用于区号 另一个用于电话号码的其余部分 然后按 查找 后 我希望能够获取两个值并将它们合并或执
  • 将事件分配给事件处理程序的两种不同类型之间的区别

    我在 SO 中看到了这个示例代码 它说一种做法不好 另一种做法很好 但我不明白为什么 事实上 我收到了著名的 RCW COM 对象错误 该帖子说这可能是一个原因 public class SomeClass private Interop