我想知道非管理资源的情况。 有人能给我一个基本的概念吗?
托管资源和非托管资源之间的基本区别是 垃圾收集器在某个时间点知道所有托管资源 GC 会出现并清理所有相关的内存和资源 GC 不知道非托管资源,例如 作为文件、流和句柄,所以如果您没有在 那么您的代码最终将导致内存泄漏和资源锁定。
从 给你偷来的,请随意阅读整篇文章。
非托管资源是运行在。NET 运行时(CLR)(又名 non-.NET 代码)例如,对 Win32API 中的 DLL 的调用,或对。用 C + + 编写的 dll。
托管资源基本上意味着由垃圾回收器管理的“托管内存”。当您不再有任何对托管对象(使用托管内存)的引用时,垃圾收集器将(最终)为您释放该内存。
那么,非托管资源就是垃圾收集器不知道的一切。例如:
通常,您希望释放那些非托管资源 之前,这样就会丢失对管理它们的对象的所有引用。为此,您可以对该对象调用 Dispose,或者(在 C # 中)使用 using语句,该语句将处理对 Dispose的调用。
Dispose
using
如果正确地忽略了非托管资源的 Dispose,那么当包含该资源的对象被垃圾收集时,垃圾收集器最终将为您处理它(这是“终结”)。但是,由于垃圾收集器不知道非托管资源,因此无法判断它需要释放这些资源的程度有多严重——因此,您的程序可能执行得很差,或者完全耗尽资源。
如果您自己实现了一个处理非托管资源的类,则由您正确实现 Dispose和 Finalize。
Finalize
“非管理资源”不是一个东西,而是一种责任。如果一个对象拥有一个非托管资源,这意味着(1)该对象之外的某个实体已经被操纵,如果不进行清理,可能会导致问题; (2)该对象拥有执行这种清理所需的信息,并负责执行清理。
尽管许多类型的非托管资源与各种类型的操作系统实体(文件、 GDI 句柄、分配的内存块等)紧密相关,但除了清理的责任之外,没有一种类型的实体是由所有这些实体共享的。通常,如果一个对象或者负责执行清理,它将具有一个 Dispose 方法,该方法指示它执行它负责的所有清理。
在某些情况下,对象会考虑到在没有人先调用 Dispose 的情况下它们可能被放弃的可能性。GC 允许对象请求通知它们已被放弃(通过调用名为 Finalize 的例程) ,并且对象可以使用这个通知来执行自己的清理。
不幸的是,像“受管理的资源”和“非受管理的资源”这样的术语被不同的人用来表示不同的东西; 坦率地说,我们认为从对象的角度来考虑更有用,要么没有任何清理责任,要么只有在调用 Dispose 时才会处理清理责任,要么有应该通过 Dispose 处理的清理责任,但也可以通过 Finalize 处理。
中为其分配内存的任何资源。NET 托管堆是托管资源。CLR 完全了解这种类型的内存,并将尽一切努力确保它不会变成孤立的内存。其他的事情都是无法控制的。例如与 COM 进行互操作,可能会在进程内存空间中创建对象,但 CLR 不会处理它。在这种情况下,跨托管边界进行调用的托管对象应该对其之外的任何事情负责。
有些用户将打开的文件、数据库连接、分配的内存、位图、文件流等排列在托管资源之间,其他用户排列在非托管资源之间
我的观点是,响应更复杂: 当您在。NET,你可能会使用一些内置的。NET 类 System.IO.File、 FileStream 或其他类。因为这很正常。NET 类中,它是托管的。但是它是一个包装器,它在内部执行“脏工作”(使用 Win32dlls 与操作系统通信,调用低级函数甚至汇编器指令) ,真正打开文件。这是什么。NET 所不知道的,非托管的。 但是您也许可以自己使用汇编器指令和旁路打开该文件。NET 文件函数。然后句柄和打开的文件是非托管资源。
DB 也是一样: 如果您使用一些 DB 程序集,那么您将拥有类似于 DbConnection 等的类,这些类是已知的。NET 和托管。但是它们包装了非托管的“脏工作”(在服务器上分配内存,与其建立连接,...)。 如果您不使用这个包装器类并自己打开某个网络套接字,并使用某些命令与自己的陌生数据库通信,那么它就是非托管的。
这些包装类(File、 DbConnection 等)是可管理的,但是它们内部使用非托管资源的方式与您相同,如果您不使用包装器并自己完成“脏活”的话。因此,这些包装器确实实现了 Dispose/Finalize 模式。他们的责任是允许程序员在不再需要包装器时释放非托管资源,并在垃圾收集包装器时释放这些资源。垃圾收集器将正确地收集包装器中的垃圾,但是内部的非托管资源将通过使用 Dispose/Finalize 模式收集。
如果你不使用内置的。NET 或第三方包装类和打开文件的一些汇编程序指令等在您的类中,这些打开的文件是非托管的,您必须实现处置/终结模式。如果你不这样做,将有内存泄漏,永久锁定资源等,即使你不再使用它(文件操作完成) ,甚至在你的应用程序终止后。
但是你的责任也是当使用这些包装。对于那些实现了释放/终结(你认识到他们,他们实现了 IDisposable) ,也实现了你的释放/终结模式,甚至释放这些包装,或者给他们释放非托管资源的信号。如果您不这样做,资源将在一些不确定的时间后释放,但它是干净的释放它立即(关闭文件立即,不让它打开和阻塞随机数分钟/小时)。因此,在类的 Dispose 方法中,可以调用所有使用的包装器的 Dispose 方法。
首先让我们了解 VB6或 C + + 程序(非 Dotnet 应用程序)是如何执行的。 我们知道计算机只能理解机器级代码。机器级代码也称为本机代码或二进制代码。因此,当我们执行 VB6或 C + + 程序时,各自的语言编译器将各自的语言源代码编译成本地代码,然后这些本地代码可以被底层的操作系统和硬件理解。
本机代码(非托管代码)特定于(本机)在其上生成的操作系统。如果您使用这个已编译的本机代码并尝试在另一个操作系统上运行,它将失败。所以这种程序执行方式的问题在于,它不能从一个平台移植到另一个平台。
现在让我们来了解一下。执行 Net 程序。使用 dotnet,我们可以创建不同类型的应用程序。一些常见的。NET 应用程序包括 Web、 Windows、控制台和移动应用程序。无论应用程序的类型如何,当您执行任何。NET 应用程序发生以下情况
那个。NET 应用程式编译成中间语言(IL)。IL 也被称为通用中间语言(CIL)和微软中间语言(MSIL)。都有。NET 和非。NET 应用程序生成程序集。程序集的扩展名为。DLL 或。EXE.例如,如果您编译一个 windows 或控制台应用,您将获得一个。EXE,当我们编译一个 web 或类库项目时,我们会得到一个。DLL.之间的区别。NET 及非。NET 汇编就是这样,DOTNET 汇编采用中间语言格式,而非 DOTNET 汇编采用本地代码格式。
非 DOTNET 应用程序可以直接运行在操作系统之上,而 DOTNET 应用程序则运行在名为“通用语言运行库”(CLR)的虚拟环境之上。CLR 包含一个名为 Just-In-Time Compiler (JIT)的组件,它将把中间语言转换为底层操作系统可以理解的本机代码。
因此,在.NET 中,应用程序的执行包括两个步骤 语言编译器,将源代码编译成中间语言(IL) 2.CLR 中的 JIT 编译器将 IL 转换成本机代码,然后可以在底层操作系统上运行这些代码。
自从。NET 程序集是中间语言格式,而不是本机代码。NET 程序集可移植到任何平台,只要目标平台具有通用语言运行库(CLR)。目标平台的 CLR 将中间语言转换为底层操作系统可以理解的本机代码。中间语言也称为托管代码。这是因为 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
非托管和托管资源基于 application domain。
application domain
根据我的理解,非托管资源就是用于连接到 outside of your application domain的所有东西。 您可以使用 HttpClient类来获取域外的数据,也可以使用 FileStream来帮助您从文件读/写。
outside of your application domain
HttpClient
FileStream
我们使用 Using块在工作完成后立即处理这些类对象,因为 GC首先关心的是进程资源的内部而不是外部,尽管它将在最后由 GC处理。
Using
GC