4

我正在尝试通过保持对对象的额外弱引用来主动确保我不会导致代码中的内存泄漏,并在应该释放它时检查它是否不再活动(这是条件代码,因此它仅在我运行时运行正在测试)。

为了简单地重现我看到的效果,创建一个新的 WPF 应用程序并在主窗口上放置一个按钮。创建另一个窗口,并在其上放置一个 TextBox。在按钮的单击处理程序中,输入以下代码:

  Window1 w = new Window1();
  WeakReference weak = new WeakReference(w);
  w.ShowDialog();
  w = null;
  // Equivalent to Application.DoEvents() just in case...
  Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate { }));
  GC.Collect();
  GC.WaitForPendingFinalizers();
  if (weak.Target != null)
    MessageBox.Show("Memory Leak");

当你运行它时,单击按钮,当窗口显示时,只需单击“x”将其关闭,什么都没有发生——一切都很好。现在做同样的事情,但是当窗口显示时,单击文本框,然后单击“x”。我每次都会收到“内存泄漏”消息。

Ants Profiler 显示 System.Windows.Documents.TextEditor 具有对 TextBox 的引用(可能仅在您聚焦 TextBox 时才设置),并且 TextBox 具有对窗口的引用。它不是真正的内存泄漏,因为如果您多次执行该过程,则会收集以前的窗口,而不是最新的。但是,这意味着我无法编写确认内存没有泄漏的测试。

我是唯一需要这种程度的保证的人,还是有其他方法?

4

4 回答 4

2

我想有些人错过了你的问题的重点。您不是试图强迫 GC 的手,而是先发制人地发现任何内存泄漏,为此我为您鼓掌。

在这种特殊情况下,似乎TextEditor(即internal)正在添加事件处理程序,并且在您的检查运行时还没有机会分离。您是否尝试过在启动调度程序之前明确地将焦点从关闭的窗口中移出?

我认为如果您尝试在您的应用程序中进行这些测试,而不是在更受控制的集成测试环境中进行这些测试,您将继续遇到此类问题,因此您可能需要重新考虑您的方法。

于 2012-06-25T08:50:13.093 回答
0

如果以前的实例被收集,这不是内存泄漏。垃圾收集器并不总是获取最新的项目,这是设计使然。如果您尝试事后猜测,您可能会遇到问题。

在真正的内存泄漏中,项目会累积而不会被回收。这是使用探查器最好检测到的东西。

于 2012-06-25T02:01:10.680 回答
0

Windows 不仅由您的代码管理,还由一些 WPF 类(如Application. 调用Collect并不能保证或证明任何事情,窗口最终会被收集。

于 2012-06-25T02:18:09.457 回答
0

尝试使用 DispatcherPriority。上下文空闲

Dispatcher.CurrentDispatcher.Invoke( DispatcherPriority.ContextIdle, new System.Action(delegate { }));
于 2012-10-03T17:58:24.357 回答