什么是非托pipe资源?
我想知道非托pipe资源。 任何人都可以请给我一个基本的想法?
托pipe资源基本上是指垃圾收集器pipe理的“托pipe内存”。 当您不再有任何对托pipe内存的托pipe对象的引用时,垃圾收集器将(最终)为您释放该内存。
非托pipe资源就是垃圾收集器不知道的一切。 例如:
- 打开文件
- 打开networking连接
- 非托pipe内存
- 在XNA中:顶点缓冲区,索引缓冲区,纹理等
通常情况下,您希望释放这些非托pipe资源, 然后将所有对引用进行pipe理的引用都丢失。 您可以通过在该对象上调用Dispose
或(在C#中)使用using
语句来处理调用Dispose
。
如果忽略正确Dispose
非托pipe资源,当包含该资源的对象被垃圾回收(这是“最终确定”)时,垃圾回收器将最终为您处理。 但是因为垃圾收集器不知道非托pipe资源,所以无法知道它需要释放多less – 所以你的程序可能执行得不好或者完全没有资源。
如果您自己实现一个处理非托pipe资源的类,则由您来正确实现Dispose
和Finalize
。
一些用户在被pipe理的资源中对打开的文件,数据库连接,分配的内存,位图,文件stream等等进行sorting,其他的在不受pipe理的资源中。 那么他们是pipe理还是非pipe理?
我的观点是,这个响应比较复杂:当你在.NET中打开文件时,你可能会使用一些内置的.NET类System.IO.File,FileStream或者其他的东西。 因为它是一个普通的.NET类,所以它被pipe理。 但是它是一个包装器,里面是“脏工作”(与使用Win32 dll的操作系统进行通信,调用低级函数甚至汇编指令)真正打开文件。 这就是.NET所不知道的,不受pipe理的。 但是,您可能可以使用汇编程序指令自行打开文件,并绕过.NET文件function。 然后句柄和打开的文件是非托pipe资源。
与DB相同:如果使用某些数据库程序集,则可以使用类似于DbConnection等的类,这些类已知.NET并进行pipe理。 但是他们包装了“不干净的工作”(在服务器上分配内存,build立连接,…)。 如果你不使用这个包装类,并自己打开一个networking套接字,并使用一些命令与自己奇怪的数据库进行通信,它是不受pipe理的。
这些包装类(File,DbConnection等)是被pipe理的,但是如果你不使用包装器并且自己做“肮脏的工作”,它们就像你一样使用非托pipe资源。 因此这些包装器实现Dispose / Finalize模式。 他们有责任允许程序员在不再需要包装器时释放非托pipe资源,并在包装器被垃圾收集时释放它们。 包装器将被垃圾收集器正确地垃圾收集,但是内部的非托pipe资源将通过使用Dispose / Finalize模式来收集。
如果您不使用内置的.NET或第三方封装类,并且在您的类中使用某些汇编程序指令等打开文件,则这些打开的文件是非托pipe的,您必须实施处理/定型模式。 如果你不这样做,将会有内存泄漏,甚至当你不再使用它(文件操作完成),甚至在你的应用程序终止之后永远locking资源等。
但是你的责任也在使用这些包装。 对于那些实现了dispose / finalize(你认识到它们,它们实现了IDisposable)的实现,还要实现你的dispose / finalize模式,并且处理这些包装或者给它们发送它们的非托pipe资源的信号。 如果不这样做,资源会在一段无限期的时间释放后立即释放(即时closures文件,不要将其打开,并随机分配几分钟/小时)。 所以在你的类的Dispose方法中,你可以调用Dispose方法来处理你所有的包装器。
非托pipe资源是在.NET运行时(CLR)(也称为非.NET代码)之外运行的资源。例如,在Win32 API中调用DLL或调用用C ++编写的.dll。
托pipe和非托pipe资源之间的基本区别在于垃圾回收器知道所有的托pipe资源,在某个时间点GC将出现并清理与托pipe对象关联的所有内存和资源。 GC不知道非托pipe资源,比如文件,stream和句柄,所以如果你没有在你的代码中明确地清理它们,那么你将最终得到内存泄漏和locking的资源。
从这里被盗,随时阅读整个post。
“非托pipe资源”不是一件事情,而是一种责任。 如果一个对象拥有一个非托pipe资源,那就意味着(1)其外部的某个实体被操纵的方式可能会导致问题,如果没有清理干净,(2)该对象具有执行这种清理所需的信息并负责为了做到这一点。
尽pipe许多types的非托pipe资源与各种types的操作系统实体(文件,GDI句柄,分配的内存块等)有很强的关联性,但除了责任之外没有单一types的实体共享清理。 通常情况下,如果一个对象有责任执行清理,它将有一个Dispose方法,指示它执行所有负责的清理。
在某些情况下,对象会考虑到可能会被放弃的可能性,而没有任何人先调用Dispose。 GC允许对象通知他们已经被放弃(通过调用一个名为Finalize的例程),对象可以使用这个通知来自己执行清理。
像“托pipe资源”和“非托pipe资源”这样的术语不幸地被不同的人用来表示不同的东西; 坦率地说,从对象的angular度来看,没有任何清理责任,清理责任只会在Dispose被调用时处理,或者通过Dispose来处理清理责任,也由Finalize负责。
在.NET托pipe堆中为其分配内存的任何资源都是托pipe资源。 CLR完全意识到这种记忆,并会尽一切努力确保它不会孤儿。 其他任何东西都是非托pipe的。 例如,与COM进行交互,可能会在进程内存空间中创build对象,但是CLR不会处理它。 在这种情况下,通过被pipe理边界进行调用的被pipe理对象应该拥有超出它的任何责任。