And*_*ell 165
托管资源基本上是指由垃圾收集器管理的"托管内存".当您不再对托管对象(使用托管内存)进行任何引用时,垃圾收集器将(最终)为您释放该内存.
然后,非托管资源就是垃圾收集器不知道的所有内容.例如:
通常,您希望在丢失对管理它们的对象的所有引用之前释放这些非托管资源.你可以通过调用Dispose该对象或(在C#中)使用using将处理调用的语句来完成此操作Dispose.
如果您Dispose正确地忽略了非托管资源,当包含该资源的对象被垃圾收集时(这是"终结"),垃圾收集器最终将为您处理它.但是因为垃圾收集器不知道非托管资源,所以它无法分析释放它们需要多么糟糕 - 所以你的程序可能表现不佳或完全耗尽资源.
如果您自己实现一个处理非托管资源的类,则由您来实现Dispose并Finalize正确实现.
Mar*_*tas 47
一些用户对托管资源中的打开文件,数据库连接,分配的内存,位图,文件流等进行排名,其他用户在非托管资源中进行排名.那么他们是管理还是不管理?
我的观点是,响应更复杂:当你在.NET中打开文件时,你可能会使用一些内置的.NET类System.IO.File,FileStream或其他东西.因为它是一个普通的.NET类,所以它是受管理的.但它是一个包装器,它内部执行"脏工作"(使用Win32 dll与操作系统通信,调用低级函数甚至汇编指令),它们真正打开文件.这就是.NET不知道的,没有管理的.但您可以使用汇编程序指令自行打开文件并绕过.NET文件函数.然后句柄和打开的文件是非托管资源.
与DB相同:如果您使用某些数据库程序集,则您拥有类似DbConnection等的类,它们已为.NET所知并受到管理.但它们包装了"脏工作",这是不受管理的(在服务器上分配内存,与它建立连接,......).如果您不使用此包装类并自行打开某个网络套接字并使用某些命令与您自己的奇怪数据库进行通信,则它是不受管理的.
这些包装类(File,DbConnection等)是受管理的,但它们内部使用非托管资源的方式与您相同,如果您不使用包装器并自己执行"脏工作".因此这些包装器实现Dispose/Finalize模式.他们有责任让程序员在不再需要包装器时释放非托管资源,并在包装器被垃圾收集时释放它们.包装器将被垃圾收集器正确地垃圾收集,但是内部的非托管资源将通过使用Dispose/Finalize模式来收集.
如果您没有在类中使用内置的.NET或第三方包装类并通过某些汇编程序指令打开文件,则这些打开的文件是不受管理的,您必须实现dispose/finalize模式.如果不这样做,即使您不再使用它(文件操作完成),甚至在应用程序终止后,也会出现内存泄漏,永久锁定的资源等.
但是你在使用这些包装时也有责任.对于那些实现dispose/finalize(你认识到它们实现了IDisposable)的人,还要实现你的dispose/finalize模式和Dispose甚至这些包装器或给它们发出信号以释放它们的非托管资源.如果不这样做,资源将在一段时间内无限期释放,但是立即释放它是干净的(立即关闭文件,不要让它打开并随机几分钟/小时随机阻止).因此,在您的类的Dispose方法中,您可以调用所有使用过的包装器的Dispose方法.
"非托管资源"不是一件事,而是一种责任.如果一个对象拥有一个非托管资源,这意味着(1)它之外的某个实体被操纵的方式可能会导致问题,如果不清理,和(2)该对象具有执行此类清理所需的信息并负责这样做.
虽然许多类型的非托管资源与各种类型的操作系统实体(文件,GDI句柄,分配的内存块等)密切相关,但除了责任之外,没有任何单一类型的实体由所有这些实体共享.清理.通常,如果一个对象有责任执行清理,它将有一个Dispose方法,指示它执行它负责的所有清理.
在某些情况下,对象会考虑在没有任何人先调用Dispose的情况下放弃它们的可能性.GC允许对象请求通知它们已被放弃(通过调用名为Finalize的例程),对象可以使用此通知自行执行清理.
不幸的是,"托管资源"和"非托管资源"等术语被不同的人用来表示不同的东西; 坦率地认为,根据对象来考虑更有用,要么没有任何清理责任,只有在调用Dispose时才会负责清理责任,或者需要通过Dispose处理清理责任,但哪些可以也可以通过Finalize来处理.
| 归档时间: |
|
| 查看次数: |
64370 次 |
| 最近记录: |