我想了解非托管资源。谁能给我一个基本的想法?
我想了解非托管资源。谁能给我一个基本的想法?
Answers:
托管资源基本上是指由垃圾回收器管理的“托管内存”。当您不再对托管对象(使用托管内存)进行任何引用时,垃圾收集器将(最终)为您释放该内存。
那么,非托管资源就是垃圾收集器所不知道的一切。例如:
通常,在丢失对管理它们的对象的所有引用之前,您要释放这些非托管资源。您可以通过调用Dispose
该对象或(使用C#)using
调用Dispose
将为您处理的语句来执行此操作。
如果您Dispose
正确地忽略了非托管资源,那么当包含该资源的对象被垃圾收集时,垃圾收集器将最终为您处理(这是“完成”)。但是,由于垃圾收集器不了解非托管资源,因此无法判断释放它们的严重程度-因此,程序性能可能很差或完全耗尽资源。
如果您自己实现一个处理非托管资源的类,则由您自己实现Dispose
和Finalize
正确执行。
Dispose
或使用using
。
IDisposable
。如果某个类确实实现IDisposable
,那么您应该在处理完该类的实例时using
或Dispose()
使用它们时将其丢弃。基于此,您可以反过来成立:如果一个类实现IDisposable
,则它可能在内部持有非托管资源。
有些用户将打开的文件,数据库连接,分配的内存,位图,文件流等在托管资源之间进行排名,而其他用户则在非托管资源之间进行排名。那么他们是受管理的还是不受管理的?
我的看法是,响应更加复杂:在.NET中打开文件时,您可能会使用一些内置的.NET类System.IO.File,FileStream或其他名称。因为它是普通的.NET类,所以可以对其进行管理。但这是一个包装程序,它实际上在内部进行“脏工作”(使用Win32 dll与操作系统进行通信,调用低级函数甚至是汇编程序指令),从而真正打开了文件。这就是.NET不了解的内容,不受管理。但是您也许可以使用汇编程序指令自己打开文件,并绕过.NET文件功能。然后,句柄和打开文件是非托管资源。
与DB相同:如果使用某些DB程序集,则具有DbConnection等类,它们是.NET已知的和托管的。但是他们包装了“脏活”,这是不受管理的(在服务器上分配内存,建立与之的连接,...)。如果您不使用此包装器类并自己打开一些网络套接字,并使用一些命令与您自己的奇怪数据库进行通信,则它将不受管理。
这些包装器类(文件,DbConnection等)是托管的,但是如果您不使用包装器并且自己做“脏活”,它们内部将以与您相同的方式使用非托管资源。因此,这些包装器确实实现了Dispose / Finalize模式。他们的责任是允许程序员在不再需要包装器时释放非托管资源,并在包装器被垃圾回收时释放它们。包装器将由垃圾收集器正确地进行垃圾收集,但是内部的非托管资源将通过使用Dispose / Finalize模式进行收集。
如果您不使用内置的.NET或第三方包装器类,而是通过类中的某些汇编程序指令等打开文件,则这些打开的文件将不受管理,并且您必须实现处理/完成模式。如果不这样做,那么即使您不再使用它(文件操作已完成),甚至在应用程序终止后,也都将发生内存泄漏,永久锁定的资源等情况。
但是,使用这些包装程序时,您也要承担责任。对于那些实现了处理/完成(您认识到它们,他们实现了IDisposable)的对象,还实现了您的处理/完成模式,甚至处理了这些包装器,或者发出了释放其非托管资源的信号。如果不这样做,则资源将在无限期的释放后被释放,但是立即释放它是干净的(立即关闭文件,并且不要在几分钟/几小时内不打开并阻止它)。因此,在类的Dispose方法中,调用所有使用的包装器的Dispose方法。
unmanaged vs managed resources
“非托管资源”不是事情,而是责任。如果对象拥有非托管资源,则意味着(1)它以外的某个实体已经以某种方式操作,如果不清理可能会引起问题,并且(2)该对象具有执行此类清理所必需的信息并负责为做到这一点。
尽管许多类型的非托管资源与各种类型的操作系统实体(文件,GDI句柄,分配的内存块等)都具有非常强的关联性,但除了它们的职责外,没有一种类型的实体可以由所有它们共享清理。通常,如果一个对象有责任执行清理,则它将具有Dispose方法,该方法指示该对象执行它负责的所有清理。
在某些情况下,对象会考虑在没有任何人首先调用“处置”的情况下将其丢弃的可能性。GC允许对象请求已被废弃的通知(通过调用名为Finalize的例程),并且对象可以使用此通知自行执行清理。
不幸的是,诸如“托管资源”和“非托管资源”之类的术语被不同的人用来表示不同的事物。坦白地说,从对象的角度考虑,要么没有任何清理责任,要么只有在调用Dispose时才负责清理责任,要么有应该通过Dispose来负责清理责任,但可以也由Finalize照顾。
在.NET托管堆中为其分配内存的任何资源都是托管资源。CLR完全了解这种内存,并将尽一切努力确保它不会被孤立。其他所有内容均不受管理。例如,与COM互操作可能会在过程存储空间中创建对象,但CLR不会处理它。在这种情况下,跨托管边界进行调用的托管对象应对超出其范围的所有内容负责。
让我们首先了解如何使用VB6或C ++程序(非Dotnet应用程序)执行。我们知道计算机只理解机器级别的代码。机器级代码也称为本地或二进制代码。因此,当我们执行VB6或C ++程序时,相应的语言编译器会将相应的语言源代码编译为本机代码,然后可由底层操作系统和硬件理解。
本机代码(非托管代码)特定于(生成本机的)操作系统。如果您使用此已编译的本机代码并尝试在其他操作系统上运行,它将失败。因此,这种程序执行方式的问题在于,它不能从一个平台移植到另一平台。
现在让我们了解一下.Net程序如何执行。使用dotnet,我们可以创建不同类型的应用程序。.NET应用程序的几种常见类型包括Web,Windows,控制台和移动应用程序。无论应用程序的类型如何,当您执行任何.NET应用程序时,都会发生以下情况
.NET应用程序被编译成中间语言(IL)。IL也称为通用中间语言(CIL)和Microsoft中间语言(MSIL)。.NET和非.NET应用程序均会生成程序集。程序集的扩展名为.DLL或.EXE。例如,如果您编译Windows或控制台应用程序,则会得到一个.EXE,而当我们编译Web或Class库项目时,就会得到一个.DLL。.NET和NON .NET程序集之间的区别在于,DOTNET程序集采用中间语言格式,而NON DOTNET程序集则采用本机代码格式。
NON DOTNET应用程序可以直接在操作系统之上运行,而DOTNET应用程序可以在称为公共语言运行时(CLR)的虚拟环境之上运行。CLR包含一个称为即时编译器(JIT)的组件,该组件会将中间语言转换为基础操作系统可以理解的本机代码。
因此,在.NET中,应用程序执行包括2个步骤:1.语言编译器,将源代码编译为中间语言(IL)。2. CLR中的JIT编译器将IL转换为本地代码,然后可以在基础操作系统上运行。
由于.NET程序集采用Intermedaite语言格式而不是本机代码,因此只要目标平台具有公共语言运行时(CLR),. NET程序集便可以移植到任何平台。目标平台的CLR将Intermedaite语言转换为底层操作系统可以理解的本机代码。中间语言也称为托管代码。这是因为CLR管理在其中运行的代码。例如,在VB6程序中,开发人员负责释放对象消耗的内存。如果程序员忘记取消分配内存,我们可能会难以检测出内存不足异常。另一方面,.NET程序员不必担心释放对象消耗的内存。CLR提供自动内存管理,也称为抓取收集。除了 从垃圾回收中,CLR还提供了其他一些好处,我们将在以后的会议中进行讨论。由于CLR正在管理和执行中间语言,因此它(IL)也称为托管代码。
.NET支持不同的编程语言,例如C#,VB,J#和C ++。C#,VB和J#只能生成托管代码(IL),而C ++可以生成托管代码(IL)和非托管代码(本机代码)。
在关闭程序后,本机代码不会永久存储在任何地方。当我们再次执行程序时,将再次生成本机代码。
.NET程序类似于Java程序执行。在Java中,我们具有字节码和JVM(Java虚拟机),而在.NET中,我们具有中间语言和CLR(公共语言运行时)
这是通过此链接提供的-他是一位了不起的老师。 http://csharp-video-tutorials.blogspot.in/2012/07/net-program-execution-part-1.html