扩展:如何使用C#的using语句释放资源?什么是IDisposable接口?与垃圾回收有什么关系?-CSDN博客
托管资源的回收有GC自动触发,而非托管资源需要手动释放。
在 C# 中,非托管资源是指那些不由 CLR(公共语言运行时)直接管理的资源,需要开发者手动进行分配和释放,常见的非托管资源包括以下几类:
操作系统资源
- 文件句柄:当使用
System.IO.FileStream
等类打开一个文件时,就会获取一个文件句柄。文件句柄是操作系统用于跟踪打开文件的一种资源,它允许程序对文件进行读取、写入等操作。如果程序打开了大量文件而没有正确关闭文件句柄,可能会导致系统资源耗尽,其他程序无法打开文件。 - 网络连接句柄:在进行网络编程时,如使用
System.Net.Sockets.Socket
类建立网络连接,会获取网络连接句柄。这些句柄用于标识与远程主机的连接,程序通过它们来发送和接收数据。如果连接使用完毕后没有关闭连接句柄,不仅会导致网络资源浪费,还可能影响系统的网络性能,甚至导致连接数达到上限,无法建立新的连接。 - 进程和线程句柄:当使用
System.Diagnostics.Process
类启动一个新进程,或者通过线程相关的 API 创建线程时,会获得进程句柄或线程句柄。这些句柄用于对进程或线程进行管理和控制,如获取进程状态、等待线程结束等。如果不正确地释放这些句柄,可能会导致系统中存在大量无用的句柄,影响系统的资源管理和性能。
图形资源
- GDI + 对象:在进行图形绘制和图像处理时,经常会使用到 GDI+(图形设备接口)对象,如
System.Drawing.Bitmap
、System.Drawing.Graphics
等。这些对象用于表示图像、画笔、字体等图形资源,它们在内存中占用一定的空间,并且与底层的图形设备相关联。如果在使用完这些对象后不释放资源,可能会导致内存泄漏和图形资源的浪费,影响图形界面的性能和稳定性。 - DirectX 资源:在开发游戏或其他需要高性能图形处理的应用程序时,可能会使用 DirectX 库。DirectX 中的资源,如纹理、顶点缓冲、索引缓冲等,都是非托管资源。这些资源需要通过特定的 API 进行创建和释放,如果不及时释放,会导致显卡内存泄漏,影响游戏的运行性能,甚至可能导致程序崩溃。
数据库连接资源
- 数据库连接对象:当使用ADO.NET等技术连接数据库时,会创建数据库连接对象,如
SqlConnection
(用于 SQL Server 数据库)、OracleConnection
(用于 Oracle 数据库)等。这些连接对象负责与数据库建立连接,并通过它们执行 SQL 语句、获取数据等操作。数据库连接是一种有限的资源,如果在使用完毕后没有关闭连接,会导致数据库连接池中的连接数量不断增加,最终可能耗尽数据库的连接资源,使其他应用程序无法连接到数据库。 - 数据库事务对象:在进行数据库事务处理时,会创建数据库事务对象,用于管理一组相关的数据库操作,确保它们要么全部成功提交,要么全部回滚。事务对象在执行过程中会占用一定的数据库资源,如果事务处理完成后没有正确释放事务对象,可能会导致数据库资源被长时间占用,影响数据库的并发性能和整体运行效率。
其他非托管资源
- COM 对象:C# 程序有时可能需要与 COM(组件对象模型)组件进行交互,通过
System.Runtime.InteropServices.Marshal
类等方式来调用 COM 对象的方法和属性。COM 对象是基于非托管代码实现的,在使用完 COM 对象后,需要通过特定的方式释放 COM 对象占用的资源,否则会导致 COM 资源泄漏,影响系统的稳定性和性能。 - 自定义非托管资源:在某些特定的场景下,开发者可能会使用一些非托管的第三方库或自己编写非托管代码来实现特定的功能,这些非托管代码所使用的资源也属于非托管资源。例如,使用 C++ 编写的动态链接库(DLL)中的资源,或者与特定硬件设备交互的驱动程序所使用的资源等。对于这些自定义的非托管资源,开发者需要根据相应的文档和规范来正确地分配和释放资源,以确保程序的正常运行和资源的有效利用。