提出问题

发布于 2024-12-02 13:27:57 字数 425 浏览 5 评论 0原文

我有许多类,它们具有实现 IDisposable 的私有成员变量(计时器、画笔等)。我需要采取什么措施来确保 .NET Framework 正确清理这些变量吗?

我遇到的文献提到“托管资源”与“非托管资源”。这些术语让我感到困惑,因为您可以拥有一个使用非托管资源实现功能的托管类。这被视为“非托管资源”还是“托管资源”?

我的理解是,如果您没有在实现 IDisposable 的对象上调用 Dispose(),那么在应用程序退出之前不会释放资源。这种情况可能会导致程序长时间运行时出现OutOfMemory异常。

如何确保我的代码正确处理资源管理?这对于这些对象很重要,因为它们是自定义控件,并且可能有大量消耗 IDisposable 资源的绘图。我尽可能使用 C# using 语句,但有时我需要使一个实现 IDisposable 的对象成为成员变量,而 using 语句对我没有帮助。

I have a number of classes which have private member variables that implement IDisposable (timers, brushes, etc). Do I need to do anything to ensure these variables are cleaned up properly by the .NET Framework?

The literature I've come across is referring to "managed resources" vs. "unmanaged resources". These terms are confusing to me because you can have a managed class which implements functionality using unmanaged resources. Is that considered an "unmanaged resource" or "managed resource" ?

My understanding is if you aren't calling Dispose() on an object that implements IDisposable, then the resources aren't being freed until the application exits. This situation could cause OutOfMemory exceptions when running the program for a long period of time.

How can I be sure my code is handling resource management correctly? It's important for these objects because they are custom controls and there may be a lot of drawing which consumes IDisposable resources. I use the C# using statement whenever I can, but sometimes I need to make an object implementing IDisposable a member variable, and the using statement won't help me there.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

蒗幽 2024-12-09 13:27:57

三个简单的规则。

托管资源可以是任何东西实现IDisposable。非托管资源类似于您通过 p/Invoke 获得的 HANDLE。像 SafeHandle 这样的类(或从 SafeHandle 派生的类)拥有非托管资源,但它本身被视为托管资源。因此,任何拥有非托管资源的类本身就是托管资源。

由于您有一个拥有托管资源的类,因此请遵循规则 2:实现 IDisposable(但不是终结器)。

IDisposable 允许提前清理。如果您不调用它,资源无论如何都会被清理(它们不会一直徘徊直到进程退出);它们稍后会被清理,并且您无法选择它们何时被清理。

Three simple rules.

A managed resource is anything implementing IDisposable. An unmanaged resource is something like a HANDLE that you got via p/Invoke. A class like SafeHandle (or one derived from SafeHandle) owns an unmanaged resource, but it is considered a managed resource itself. So any class that owns unmanaged resource is itself a managed resource.

Since you have a class owning managed resources, follow Rule 2: implement IDisposable (but not a finalizer).

IDisposable allows for earlier cleanup. If you don't call it, the resources will be cleaned up anyway (they won't hang around until process exit); they'll just be cleaned up later, and you don't have a choice about when they get cleaned up.

夏夜暖风 2024-12-09 13:27:57

是的 - 如果您的类“包含”IDisposable,那么该类也应该几乎实现IDisposable

“托管”资源基本上是内存。 “非托管”资源可以是文件句柄、网络连接、图形对象句柄等。在大多数情况下,可以直接访问本机句柄的类型具有终结器,因此资源将在某个时刻被释放,但是最好显式释放它 - 在某些情况下(例如使用 HttpWebResponse),可用的此类资源数量可能有限(在这种情况下,连接池中到单个主机的连接)并且您最终可能会超时等待要释放的“死”资源。

在可能的情况下,最好不要首先拥有此类成员 - 将它们作为局部变量等的方法参数,这样您就可以使用它们,然后关闭它们,而无需将资源的生命周期与你的对象的生命周期。但是,在某些情况下这是不合适的 - 在这种情况下您应该实现 IDisposable

Yes - if your class "contains" an IDisposable, that class should almost certainly implement IDisposable too.

"Managed" resources are basically memory. "Unmanaged" resources can be file handles, network connections, handles to graphics objects etc. In most cases types which have direct access to native handles have finalizers, so the resource will be released at some point, but it's still better to release it explicitly - in some cases (such as with HttpWebResponse) there can be a limited number of such resources available (connections in a connection pool to a single host in this case) and you can end up timing out waiting for a "dead" resource to be freed.

Where possible, it's nicer not to have such class members in the first place - have them as method parameters of local variables etc, so you can use them and then close them without tying the lifetime of the resource to the lifetime of your object. However, in some cases that's not appropriate - in which case you should implement IDisposable.

星軌x 2024-12-09 13:27:57

非常全面的 IDisposable 指南位于此处

不要传递地处理您的类型中定义的任何一次性字段
来自您的 Dispose 方法。

您应该在任何字段上调用 ​​Dispose()
您的对象控制其生命周期。例如,考虑一个案例
其中您的对象拥有一个私有 TextReader 字段。在你的类型中
Dispose,你应该调用TextReader对象的Dispose,这将
依次处理其一次性字段(Stream 和 Encoding,例如
例如),等等。如果在 Dispose(bool disducing) 内实现
方法,只有当处理参数为
true — 期间不允许触摸其他管理对象
最终确定。此外,如果您的对象不拥有给定的
一次性物品,不应像其他物品一样尝试处置它
代码仍然可以依赖它的活动。这两种情况都可能导致
难以察觉的错误。

当您的类型未密封并且
包含明确需要或可以释放的资源,例如
例如原始句柄或其他非托管资源。

这个图案
为开发人员提供了一种标准化的方法来确定性地
销毁或释放对象拥有的资源。它还有助于子类
正确释放基类资源。

“非托管资源”通常是指您的代码直接引用本机句柄(文件句柄、连接、套接字等)的情况。在这种情况下,您还必须实现终结器或使用 安全句柄。大多数时候,您通过 TextReader 等 .NET 类间接引用本机句柄。在这种情况下,您可以简单地使用“using”,或者如果您正在编写库,则可以传递地实现 IDisposable。

Very comprehensive IDisposable guidelines are here.

Do transitively dispose of any disposable fields defined in your type
from your Dispose method.

You should call Dispose() on any fields
whose lifecycle your object controls. For example, consider a case
where your object owns a private TextReader field. In your type's
Dispose, you should call the TextReader object's Dispose, which will
in turn dispose of its disposable fields (Stream and Encoding, for
example), and so on. If implemented inside a Dispose(bool disposing)
method, this should only occur if the disposing parameter is
true—touching other managed objects is not allowed during
finalization. Additionally, if your object doesn’t own a given
disposable object, it should not attempt to dispose of it, as other
code could still rely on it being active. Both of these could lead to
subtle-to-detect bugs.

Do implement the dispose pattern when your type is unsealed and
contains resources that explicitly need to be or can be freed, for
example raw handles, or other unmanaged resources.

This pattern
provides a standardized means for developers to deterministically
destroy or free resources owned by an object. It also aids subclasses
to correctly release base class resources.

'Unmanaged resource' usually refers to cases where your code refernces native handles directly (file handles, connections, sockets etc). In this case you would also have to implement finalizer or use SafeHandle. Most of the time you reference native handles indirectly, through .NET classes like TextReader. In this case you can simply use 'using' or, if you are writing library, implement IDisposable transitively.

安静被遗忘 2024-12-09 13:27:57

如果您的类具有实现 IDisposable 的成员变量,那么您的类也应该实现它。你清理你所拥有的东西。

If your class has member variables that implement IDisposable, then your class should implement it as well. You clean up what you own.

拒绝两难 2024-12-09 13:27:57

您的理解中有一些好的信息和一些错误的信息。

总而言之,您需要 Dispose() 任何实现 IDisposable 的东西。

由于这些是类的私有成员变量,如果这些变量应该在该类的实例的生命周期内可用,那么您的类还应该实现 IDisposable 和 < code>Dispose() 在其自己的 Dispose() 方法中处理这些类型。

如果这些私有成员变量的生命周期有限(即仅在一个方法内),只需将它们包装在 using 块中。

You have some good information and some misinformation in your understanding.

The long and short of it is that you need to Dispose() anything that implements IDisposable.

Being as these are private member variables of your class, and if these are supposed to be available for the lifetime of instances of that class, your class should also implement IDisposable and Dispose() of those types in its own Dispose() method.

If those private member variables have a limited lifetime (i.e. only within one method), just wrap them in a using block.

风轻花落早 2024-12-09 13:27:57

1) 您可以使用内存分析器工具,网上有很多,我知道的最好的是 Reg Gate 的 ANTS Profiler。

2)我的经验法则是,事件必须始终取消订阅,并且如果一次性对象(流等)是成员变量并且保存它们的对象被销毁,则它们将被自动处置。
例如,如果您在方法中创建本地一次性对象,则必须处置它,或者只是将其放入 using 语句中然后忘记它;)

1) You can use a Memory Profiler Tool, there are plenty around the web, the best i know being Reg Gate's ANTS Profiler.

2) My rule of thumb is that events must always be unsubscribed, and disposable objects (Streams etc) will be disposed automatically if they're member variables and the object holding them gets destroyed.
If you create a local disposable object in a method for example, you must dispose it, or just put it in a using statement and forget about it ;)

夜夜流光相皎洁 2024-12-09 13:27:57

我认为描述托管资源是最有帮助的,它是一个实现 IDisposable 并需要清理的类类型对象,但如果它在没有正确处理的情况下被放弃,则可以执行此类清理(通常使用 Finalize)。非托管资源通常是指需要清理的实体,如果在没有首先处理的情况下就将其放弃,则根本不会发生这种情况。需要注意的是,虽然术语“托管资源”基本上专门指类类型对象(通常会覆盖 Finalize,但在某些情况下可能是 WeakReference 对象的目标),但非托管资源可能不仅是 任何东西,它们也可能在任何地方,包括在另一台计算机上。

我建议不要使用“资源”一词,而用“责任”来思考会更有帮助。打开文件或套接字连接会产生关闭它的责任。获取锁会产生释放锁的责任。向远程系统发送“授予我对此记录的独占访问权限”消息会产生向远程系统发送“我已完成此记录”消息的责任。如果一个对象的清理职责即使被放弃也能执行,那么它就是一个“托管资源”。否则,它是“非托管资源”。

仅仅将事物分类为“托管资源”或“非托管资源”并不足以决定如何清理它们。一些非托管职责可以通过类类型包装器方便地处理,该包装器可以在不当放弃的情况下执行任何必要的清理。此类包装器通常应包含执行清理职责所需的最少量信息。其他责任不能很好地自动处理。确保调用 Dispose 通常比尝试处理未调用 Dispose 时可能发生的所有情况要好。

I think it's most helpful to describe a managed resource is a class-type object that implements IDisposable and requires cleanup, but can perform such cleanup (typically using Finalize) if it's abandoned without being properly Dispose'd. An unmanaged resource generally refers to an entity which requires cleanup that simply won't happen if it's abandoned without being Dispose'd first. It's important to note that the while the term "managed resource" refers essentially exclusively to class-type objects (which generally override Finalize, but which in some cases may be the targets of WeakReference objects), unmanaged resources may be not only be anything, they may also be anywhere, including on another computer.

I would suggest that instead of using the term "resource" it's more helpful to think in terms of "responsibilities". Opening a file or socket connection creates a responsibility to close it. Acquiring a lock creates a responsibility to release it. Sending a remote system a "grant me exclusive access to this record" message creates a responsibility to send it an "I'm done with this record" message. If an object's cleanup responsibilites can get carried out even if it's abandoned, it's a "managed resource". Otherwise, it's an "unmanaged resource".

Merely categorizing things as "managed resources" or "unmanaged resources" is not quite sufficient for deciding how they should be cleaned up. Some unmanaged responsibilities can be conveniently handled by a class-type wrapper which can perform any necessary cleanup in case of improper abandonment. Such wrappers should generally contain a minimal amount of information necessary to perform the cleanup responsibility. Other responsibilities cannot very well be handled automatically. It's often better to ensure Dispose is called than try to handle everything that can happen if it isn't.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文