【问题标题】:Events and Memory Leaks in .NET.NET 中的事件和内存泄漏
【发布时间】:2009-12-03 22:04:29
【问题描述】:

我正在使用 C# .NET 3.5 ...并且我一直致力于通过将与数据库相关的活动移动到单独的工作对象中来解耦 BLL 对象。工作对象将实体添加到数据库并将成功或失败消息返回给 BLL 对象。

当我在 BLL 中实例化工作对象时,我连接工作人员的事件并使用 event += delegate(eventhandler) 语法设置 BLL 的事件处理程序。

我听说,如果我在处理 worker 时没有使用 -= 语法显式取消侦听器的连接,则可能存在内存泄漏。

所有这些处理都发生在 Windows 服务中,该服务从队列中提取消息并调用适当的 BLL 对象......我担心我可能会在这个过程中引入内存泄漏。

【问题讨论】:

    标签: .net events memory-leaks


    【解决方案1】:

    订阅事件会添加从订阅者到提供者的引用。

    x.Event += y.handler 表示 x 现在持有对 y 的引用

    如果 x 的生命周期比 y 长,那么在对 x 的所有引用消失之前,y 不能被垃圾回收。

    在您的情况下,您正在收听 BLL 中工作人员的事件(如果我理解正确的话),那么除非您明确取消订阅,否则您可以参考留在 BLL 中的工作人员。

    但是,如果您在完成 BLL 的同时与工人一起完成,那么这实际上并不重要。

    【讨论】:

    • 是的,这是正确的,我正在监听来自 BLL 中工作人员的事件。一旦工作完成,BLL 和工人都会离开。接线是:worker.errorevent += new worker.error(BLLsMethod) 我想知道的是在清理 BLL 时我需要取消接线,但正如你所说,因为一旦这个过程,worker 和 BLL 都会消失完成了那我就不用担心这个了。
    • “订阅事件会添加从订阅者到提供者的引用” - 它不会创建从事件发布者到事件订阅者的引用,因为发布者需要能够调用该方法在订阅者上,它持有对该方法的引用,因此也是订阅者。
    【解决方案2】:

    你听到的是真的。只要您的对象订阅了来自另一个可访问对象的事件,运行时就不会释放订阅者对象。如果您的应用程序在其生命周期的开始创建一个或一小组工作对象,那么您应该没问题。如果应用程序为每个 BLL 对象创建了一个工作对象,但对 BLL 实例的引用被释放,你也应该没问题。

    危险的是盲目地订阅一个实例方法到static事件或者一个生命周期长的对象的实例事件。

    【讨论】:

    • " 只要你的对象订阅了另一个可达对象的事件,运行时就不会释放那个对象" 不是反过来吗。只要您的对象订阅了来自另一个可达对象的事件,那么运行时将不会释放 your 对象,因为可达(事件发布者)引用了您,即事件订阅者。或者也许这就是你的意思,我只是看错了
    • @Foo42 是的,当我写 that 时,我的意思是指 your。当我现在阅读它时,我看到了歧义。
    【解决方案3】:

    如果您在服务中只订阅过一次活动,应该没问题。

    【讨论】:

      【解决方案4】:

      研究使用 .NET 后台工作程序或线程池以及这些解决方案可用的同步机制。

      【讨论】:

      • 什么?这有什么关系?
      • 我相信作者在谈论一个典型的单位工作情况。根据我的经验,作者提到的大多数工作同步错误都可以通过有效地使用 .NET 后台工作或线程池来避免。
      • 对不起,我应该澄清这一点......我没有创建一个单独的线程来完成工作并与事件进行通信,我只是在主线程中创建一个工作对象并告诉它去工作。要写入响应输出的消息从工作人员返回,因为它不知道如何处理响应。如果有更好的技术可以做到这一点(例如可能将 BLL 的引用传递给工作人员,然后从工作人员那里调用 BLL 的方法,那么我很想听听有关此主题的更多信息。)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-22
      • 2012-05-29
      • 2012-02-19
      • 1970-01-01
      • 2022-12-06
      • 1970-01-01
      相关资源
      最近更新 更多