在WPF控件中处理对象的释放

4

我在使用一个实现了IDisposable接口的对象来创建WPF自定义控件。当控件被GC回收时,如何确保该对象被正确释放?由于Control类中没有Dispose()或其他可以覆盖以释放该对象的方法。


1
这取决于您如何使用此对象。您能展示一下代码吗? - Alex Aza
4个回答

1

我认为如果您遵循MVVM设计模式,那么资源应该保存在模型或视图模型中。

此外,应使用弱事件模式来附加事件。


1
如果您正在使用需要处理的对象,请尝试使用Application.Shutdown方法在关闭时释放资源,或者尝试Unloaded事件在从可视树中移除控件时释放资源。您可能需要同时使用这两种方法。
请尝试查看this问题是否有帮助。

这个问题并没有真正解决问题。它不是答案。为什么在应用程序关闭时调用dispose,当操作系统会重新获取内存呢?如果用户正在关闭应用程序,则内存泄漏不再是问题,因为他们不再使用该应用程序。Unloaded不会被Windows.Close()调用。它似乎更像一个随机函数而已。最好的方法可能是创建自己的Unloaded方法,并在Window.Close()上调用它,尽管可能会有许多问题。 - Michael T

0

如果尚未调用,则终结器应调用Dispose。如果您正在处理.NET类型,则可以确保它会这样做。当对象被GC'd时,终结器将被调用,您将没问题。

这对于像显示Bitmap的控件(例如Picturebox)非常典型。除非您经常更换该位图(在这种情况下,您应该处理它),否则您可能可以不过分谨慎地使用它。

话虽如此,这取决于您的应用程序及其工作方式。如果您有许多实现IDisposable但不再需要的对象,并且可能有相对较长时间的活动引用,则应更加积极并创建一种方案,以尽可能确定地清除这些内容。


问题在于WPF控件没有Dispose方法。 - Chris
@user775602:没错,因为他们不需要它,那为什么会是个问题呢? - Ed S.
1
问题在于他正在将一个非WPF项添加到他的WPF UserControl中。例如,他可以在他的WPF UserControl中声明一个BackgroundWorker。UserControl不需要dispose,但BackgroundWorker需要。他应该什么时候调用它?我写了一个答案。 - Michael T
@Michael:好吧,我想他应该在需要的时候调用它。鉴于问题中提供的信息不足,这是无法回答的。既然他编写了用户控件,那么在某个时刻调用Dispose或在Unloaded事件中执行Dispose应该很简单(当然,假设这样做是安全的)。 - Ed S.
1
问题是,未加载事件没有被调用。这必须是最常见的WPF问题之一,一旦你意识到问题,这是一个非常好的问题。而且,这个问题在这个网站上到处都是,我认为我的答案是最好的。这里有另一个非常相似的问题示例:https://dev59.com/Q3I_5IYBdhLWcg3wK_s6 - Michael T

0

昨晚我处理了这个问题。也就是说,我需要在UserControl中调用一个对象的dispose方法。我认为你有两个选择。

我向WPF UserControl添加了BackgroundWorker的实例。这可能是一个好主意,也可能不是。每个UserControl只需要运行一个BackgroundWorker实例。因此,我将BackgroundWorker初始化为null。当我需要使用BackgroundWorker时,我检查它是否为null,然后创建一个新的实例,让它完成工作。然后,在worker完成事件中对其进行处理,并将其设置回null。

您可以使用WPF Window关闭或卸载事件。Unload不会在UserControl上调用,但在包含该UserControl的Window中会调用。

WPFWindow事件Close(或Unload或其他)调用您的UserControl中的自定义释放函数。这个自定义释放函数会完成工作。

所以,对于你的问题,没有一个真正好的通用解决方案。需要更多的设计和思考来处理需要dispose的功能,因为一般情况下,WPF不需要dispose。通常只需要将项目设置为null即可。(当你将UserControl设置为null时,UserControl.Unload是否会被调用?我之前没有考虑过,但如果是,那就是正确的答案。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接