I was reading the MSDN article about how to implement IDisposable and I am uncertain about the difference between managed and native resources cited in the article.
我正在阅读MSDN关于如何实现IDisposable的文章,我不确定文章中提到的托管资源和原生资源之间的区别。
I have a class that must dispose 2 of its fields when it is disposed. Should I treat them as Managed (dispose only when disposing = true) or Native resources?
我有一个类,当它被处理时,它必须处理它的两个字段。我应该将它们视为托管资源(仅在处理= true时才处理)还是原生资源?
3 个解决方案
#1
18
A managed resource is another managed type, which implements IDisposable
. You need to call Dispose()
on any other IDisposable
type you use. Native resources are anything outside the managed world such as native Windows handles etc.
托管资源是另一种托管类型,它实现IDisposable。您需要对使用的任何其他IDisposable类型调用Dispose()。本机资源是管理世界之外的任何东西,如本机Windows句柄等。
EDIT: Answer to question in comment (too long for comment)
编辑:在评论中回答问题(评论时间太长)
No that is just a managed type. A correctly constructed type, which doesn’t implement IDisposable
will be handled by the garbage collector and you don’t have to do anything else. If your type uses a native resource directly (e.g. by calling Win32 libraries), you must implement IDisposable
on your type and dispose of the resource(s) in the Dispose
method. If your type uses a native resource encapsulated by another type which implements IDisposable
, you must call Dispose()
on instances of this type in the Dispose
method of your type.
不,那只是一个托管类型。一个正确构造的类型(它没有实现IDisposable)将由垃圾收集器处理,而你不需要做其他任何事情。如果类型直接使用本机资源(例如通过调用Win32库),则必须对类型实现IDisposable,并在dispose方法中处置资源。如果您的类型使用的本机资源是由另一种实现IDisposable的类型封装的,那么您必须在类型的Dispose方法中调用Dispose()。
#2
21
To add a little to Brian's answer, and your comment/question:
为了给布莱恩的回答增加一些内容,以及你的评论/问题:
The difference between a Managed/Unmanaged resource is that the Garbage Collector is aware of managed resources and isn't aware of unmanaged resources. I know that answer isn't very concrete but the difference is huge.
托管/非托管资源的区别在于,垃圾收集器知道托管资源,而不知道非托管资源。我知道答案不是很具体,但差别很大。
To help draw the line in the sand here is the short (and probably riddled with little errors) version of how GC runs and cleans up memory:
为了帮助在这里划清界限,这里有一个简短的(可能还会有一些小错误)版本的GC如何运行和清理内存:
The garbage collector is aware of all managed objects but when garbage collection runs it doesn't initially know if any given object is still in use or is elegible to be released. It determines whether or not it can cleanup an object by initially marking all objects as garbage, then traversing from the application root to all referenced objects. Each object that has a relationship back to the root (a reference, either direct or indirect) gets marked as reachable and is no longer considered garbage. After the GC runs through every reachable object it cleans up the rest since they are no longer in use.
垃圾收集器知道所有被管理的对象,但是当垃圾收集运行时,它并不知道是否有任何给定的对象仍然在使用,或者是可以被释放的。它首先将所有对象标记为垃圾,然后从应用程序根遍历到所有引用的对象,从而确定是否可以清理对象。每个与根(直接或间接引用)有关系的对象都被标记为可到达的,不再被认为是垃圾。在GC遍历每个可访问对象之后,它将清理其余的对象,因为它们不再使用。
In almost all cases working with .NET framework objects you can be assured that objects are managed (.NET provides managed wrappers of nearly all unmanaged resources to ensure they are properly cleaned up); other third party components which hook into the Win32 API (or your components which do this) are the objects which may be cause for concern.
在几乎所有使用. net framework对象的情况下,您都可以确信对象是被管理的(。NET提供了几乎所有非托管资源的托管包装器,以确保它们得到了适当的清理);连接到Win32 API(或这样做的组件)的其他第三方组件可能会引起关注。
There are some .NET objects which can be considered to be somewhat unmanaged. Components of the Graphics library are one example.
有一些。net对象可以被认为是不受管理的。图形库的组件就是一个例子。
Most ".NET Memory leaks" aren't really memory leaks in the true sense. Typically they occur when you think you have removed an object from use but in fact the object still has some reference to the application. A common example is adding eventhandlers (obj.SomeEvent += OnSomeEvent -or- AddHandler obj.SomeEvent, AddressOf OnSomeEvent) and not removing them.
大多数”。网络内存泄漏“并不是真正意义上的内存泄漏。通常,当您认为已经从使用中删除了一个对象时,它们就会发生,但实际上该对象仍然具有对应用程序的引用。一个常见的例子是添加偶数项(obj)。SomeEvent += OnSomeEvent - AddHandler obj。某事件,对某事件的寻址)而不是删除它们。
These 'lingering references' are technically not memory leaks since your application is still technically using them; however if there are enough of them your application can suffer severe performance impacts and may show signs of resource issues (OutOfMemoryExceptions, unable to attain window handles, etc).
这些“延迟引用”在技术上不是内存泄漏,因为您的应用程序仍然在技术上使用它们;但是,如果有足够的内存,您的应用程序可能会受到严重的性能影响,并可能出现资源问题的迹象(outofmemoryexception,无法获得窗口句柄,等等)。
I'm an intermediate .NET developer and unfortunately know about these problems first-hand. I recommend playing with ANTS Profiler to help become familiar with lingering references (there is a free trial version) or if you want to get a little bit more nitty-gritty research using WinDbg and SOS.DLL to look at the managed heap. If you decide to look into the latter I recommend reading Tess Ferrandez' blog; she has a lot of great tutorials and advice on using Windbg effectively
我是一个中级的。net开发人员,不幸的是,我直接知道这些问题。我建议您与ant Profiler一起玩,以帮助您熟悉延迟引用(有一个免费试用版),或者如果您想使用WinDbg和SOS进行更深入的研究。用于查看托管堆的DLL。如果你决定研究后者,我建议你阅读Tess Ferrandez的博客;关于如何有效地使用Windbg,她有很多很棒的教程和建议
#3
1
The short answer would be anything that you go behind the CLR's back (to the OS) to obtain can be termed as 'native'.
简短的回答是您在CLR背后(到操作系统)获得的任何东西都可以称为“本机”。
- unmanaged memory allocation. If you 'new' up a chunk of memory in a managed class CantStayManaged, then CantStayManaged is responsible for freeing this memory (resource).
- 非托管内存分配。如果在托管类CantStayManaged中“新建”一个内存块,那么CantStayManaged负责释放这个内存(资源)。
- handles to files, pipes, events, synchronization constructs, etc. - as a thumb rule if you call WinAPIs to obtain pointers/handles to a resource, then those are 'native resources'
- 文件句柄、管道句柄、事件句柄、同步构造句柄等-作为一个经验规则,如果您调用winapi来获取指向资源的指针/句柄,那么这些就是“本地资源”
So now CantStayManaged has 2 things it needs to cleanup before it bids adieu.
所以现在CantStayManaged有两件事需要清理,然后再投标。
- Managed: Member fields and any resources the CLR allocated. This usually equates to calling Dispose on your 'Disposable' member objects.
- 管理:成员字段和CLR分配的任何资源。这通常等同于调用“一次性”成员对象上的Dispose。
- Unmanaged: all the sneaky low-level stuff we pull behind its back.
- 无管理的:所有卑鄙的低层次的东西,我们拖在它背后。
There are 2 ways the object cleanup can be triggered now.
现在有两种方法可以触发对象清理。
- Dispose(true) case: You called Dispose explicitly on your type. Good programmer.
- Dispose(true)情况:在类型上显式地调用Dispose。优秀的程序员。
- Dispose(false) case: You forgot to call Dispose, in which case the finalizer should kick in and still ensure proper cleanup.
- 处理(错误)情况:您忘记调用Dispose,在这种情况下终结器应该启动并确保适当的清理。
In both cases, the unmanaged resources should be freed up else 'LEAKS!', 'CRASHES!' et.all surface. But you should only attempt to cleanup managed resources only in Dispose() former case. In the latter/finalizer case - the CLR might have already finalized and collected some of your members, so you shouldn't access them (CLR doesn't guarantee an order in which an object graph is finalized.) Hence you avoid issues by guarding your managed cleanup with an if (AmIBeingCalledFromDispose)
guard check
在这两种情况下,非托管资源都应该被释放出来,否则就会泄漏!”、“崩溃!“et.all表面。但是,您应该只尝试清除Dispose()中的托管资源。在后一种/终结器的情况下——CLR可能已经完成并收集了一些成员,所以您不应该访问它们(CLR并不保证对象图已经完成的顺序)。因此,通过使用if(类似于命名为fromdispose)保护托管清理,可以避免出现问题
HTH
HTH
#1
18
A managed resource is another managed type, which implements IDisposable
. You need to call Dispose()
on any other IDisposable
type you use. Native resources are anything outside the managed world such as native Windows handles etc.
托管资源是另一种托管类型,它实现IDisposable。您需要对使用的任何其他IDisposable类型调用Dispose()。本机资源是管理世界之外的任何东西,如本机Windows句柄等。
EDIT: Answer to question in comment (too long for comment)
编辑:在评论中回答问题(评论时间太长)
No that is just a managed type. A correctly constructed type, which doesn’t implement IDisposable
will be handled by the garbage collector and you don’t have to do anything else. If your type uses a native resource directly (e.g. by calling Win32 libraries), you must implement IDisposable
on your type and dispose of the resource(s) in the Dispose
method. If your type uses a native resource encapsulated by another type which implements IDisposable
, you must call Dispose()
on instances of this type in the Dispose
method of your type.
不,那只是一个托管类型。一个正确构造的类型(它没有实现IDisposable)将由垃圾收集器处理,而你不需要做其他任何事情。如果类型直接使用本机资源(例如通过调用Win32库),则必须对类型实现IDisposable,并在dispose方法中处置资源。如果您的类型使用的本机资源是由另一种实现IDisposable的类型封装的,那么您必须在类型的Dispose方法中调用Dispose()。
#2
21
To add a little to Brian's answer, and your comment/question:
为了给布莱恩的回答增加一些内容,以及你的评论/问题:
The difference between a Managed/Unmanaged resource is that the Garbage Collector is aware of managed resources and isn't aware of unmanaged resources. I know that answer isn't very concrete but the difference is huge.
托管/非托管资源的区别在于,垃圾收集器知道托管资源,而不知道非托管资源。我知道答案不是很具体,但差别很大。
To help draw the line in the sand here is the short (and probably riddled with little errors) version of how GC runs and cleans up memory:
为了帮助在这里划清界限,这里有一个简短的(可能还会有一些小错误)版本的GC如何运行和清理内存:
The garbage collector is aware of all managed objects but when garbage collection runs it doesn't initially know if any given object is still in use or is elegible to be released. It determines whether or not it can cleanup an object by initially marking all objects as garbage, then traversing from the application root to all referenced objects. Each object that has a relationship back to the root (a reference, either direct or indirect) gets marked as reachable and is no longer considered garbage. After the GC runs through every reachable object it cleans up the rest since they are no longer in use.
垃圾收集器知道所有被管理的对象,但是当垃圾收集运行时,它并不知道是否有任何给定的对象仍然在使用,或者是可以被释放的。它首先将所有对象标记为垃圾,然后从应用程序根遍历到所有引用的对象,从而确定是否可以清理对象。每个与根(直接或间接引用)有关系的对象都被标记为可到达的,不再被认为是垃圾。在GC遍历每个可访问对象之后,它将清理其余的对象,因为它们不再使用。
In almost all cases working with .NET framework objects you can be assured that objects are managed (.NET provides managed wrappers of nearly all unmanaged resources to ensure they are properly cleaned up); other third party components which hook into the Win32 API (or your components which do this) are the objects which may be cause for concern.
在几乎所有使用. net framework对象的情况下,您都可以确信对象是被管理的(。NET提供了几乎所有非托管资源的托管包装器,以确保它们得到了适当的清理);连接到Win32 API(或这样做的组件)的其他第三方组件可能会引起关注。
There are some .NET objects which can be considered to be somewhat unmanaged. Components of the Graphics library are one example.
有一些。net对象可以被认为是不受管理的。图形库的组件就是一个例子。
Most ".NET Memory leaks" aren't really memory leaks in the true sense. Typically they occur when you think you have removed an object from use but in fact the object still has some reference to the application. A common example is adding eventhandlers (obj.SomeEvent += OnSomeEvent -or- AddHandler obj.SomeEvent, AddressOf OnSomeEvent) and not removing them.
大多数”。网络内存泄漏“并不是真正意义上的内存泄漏。通常,当您认为已经从使用中删除了一个对象时,它们就会发生,但实际上该对象仍然具有对应用程序的引用。一个常见的例子是添加偶数项(obj)。SomeEvent += OnSomeEvent - AddHandler obj。某事件,对某事件的寻址)而不是删除它们。
These 'lingering references' are technically not memory leaks since your application is still technically using them; however if there are enough of them your application can suffer severe performance impacts and may show signs of resource issues (OutOfMemoryExceptions, unable to attain window handles, etc).
这些“延迟引用”在技术上不是内存泄漏,因为您的应用程序仍然在技术上使用它们;但是,如果有足够的内存,您的应用程序可能会受到严重的性能影响,并可能出现资源问题的迹象(outofmemoryexception,无法获得窗口句柄,等等)。
I'm an intermediate .NET developer and unfortunately know about these problems first-hand. I recommend playing with ANTS Profiler to help become familiar with lingering references (there is a free trial version) or if you want to get a little bit more nitty-gritty research using WinDbg and SOS.DLL to look at the managed heap. If you decide to look into the latter I recommend reading Tess Ferrandez' blog; she has a lot of great tutorials and advice on using Windbg effectively
我是一个中级的。net开发人员,不幸的是,我直接知道这些问题。我建议您与ant Profiler一起玩,以帮助您熟悉延迟引用(有一个免费试用版),或者如果您想使用WinDbg和SOS进行更深入的研究。用于查看托管堆的DLL。如果你决定研究后者,我建议你阅读Tess Ferrandez的博客;关于如何有效地使用Windbg,她有很多很棒的教程和建议
#3
1
The short answer would be anything that you go behind the CLR's back (to the OS) to obtain can be termed as 'native'.
简短的回答是您在CLR背后(到操作系统)获得的任何东西都可以称为“本机”。
- unmanaged memory allocation. If you 'new' up a chunk of memory in a managed class CantStayManaged, then CantStayManaged is responsible for freeing this memory (resource).
- 非托管内存分配。如果在托管类CantStayManaged中“新建”一个内存块,那么CantStayManaged负责释放这个内存(资源)。
- handles to files, pipes, events, synchronization constructs, etc. - as a thumb rule if you call WinAPIs to obtain pointers/handles to a resource, then those are 'native resources'
- 文件句柄、管道句柄、事件句柄、同步构造句柄等-作为一个经验规则,如果您调用winapi来获取指向资源的指针/句柄,那么这些就是“本地资源”
So now CantStayManaged has 2 things it needs to cleanup before it bids adieu.
所以现在CantStayManaged有两件事需要清理,然后再投标。
- Managed: Member fields and any resources the CLR allocated. This usually equates to calling Dispose on your 'Disposable' member objects.
- 管理:成员字段和CLR分配的任何资源。这通常等同于调用“一次性”成员对象上的Dispose。
- Unmanaged: all the sneaky low-level stuff we pull behind its back.
- 无管理的:所有卑鄙的低层次的东西,我们拖在它背后。
There are 2 ways the object cleanup can be triggered now.
现在有两种方法可以触发对象清理。
- Dispose(true) case: You called Dispose explicitly on your type. Good programmer.
- Dispose(true)情况:在类型上显式地调用Dispose。优秀的程序员。
- Dispose(false) case: You forgot to call Dispose, in which case the finalizer should kick in and still ensure proper cleanup.
- 处理(错误)情况:您忘记调用Dispose,在这种情况下终结器应该启动并确保适当的清理。
In both cases, the unmanaged resources should be freed up else 'LEAKS!', 'CRASHES!' et.all surface. But you should only attempt to cleanup managed resources only in Dispose() former case. In the latter/finalizer case - the CLR might have already finalized and collected some of your members, so you shouldn't access them (CLR doesn't guarantee an order in which an object graph is finalized.) Hence you avoid issues by guarding your managed cleanup with an if (AmIBeingCalledFromDispose)
guard check
在这两种情况下,非托管资源都应该被释放出来,否则就会泄漏!”、“崩溃!“et.all表面。但是,您应该只尝试清除Dispose()中的托管资源。在后一种/终结器的情况下——CLR可能已经完成并收集了一些成员,所以您不应该访问它们(CLR并不保证对象图已经完成的顺序)。因此,通过使用if(类似于命名为fromdispose)保护托管清理,可以避免出现问题
HTH
HTH