.NET 内存管理两种有效的资源释放方式
前言
嗨,大家好!今天我们要聊一聊 .NET 中的内存管理。你知道吗?虽然 .NET 有一个很好的垃圾回收系统来自动清理不再使用的对象,但在某些情况下,我们还需要自己动手来释放一些特殊的资源,比如打开的文件或数据库连接。如果不这样做,可能会导致程序运行不畅甚至崩溃。在本文里,将介绍两种简单有效的方式来管理这些资源:使用 using 语句和显式调用 Dispose 方法。这两种方式可以我们更有效地控制资源的生命周期,避免内存泄漏等问题,确保应用程序的健壮性。不管是刚入门的小白还是技术大牛,希望你能从这篇文章中学有用的知识和技巧,让我们的程序运行的更稳、更靠谱。
正文
在 .NET 中内存管理主要依赖于垃圾回收机制,主要是指内存管理和非托管资源的释放。但是,有时候我们可能需要更细粒度地控制某些资源的释放。两种主要的方式进行处理
- 垃圾回收(GC)
- 确认性资源释放(DRD)
官网相关文档https://learn.microsoft.com/zh-cn/dotnet/standard/managed-code
垃圾回收(Garbage Collection)
垃圾回收是 .NET 中一个非常重要的自动内存管理机制。它帮助我们自动清理不再使用的对象,并释放这些对象占用的内存,避免了手动管理内存的繁琐的工作,使我们能够更加专注于编写业务逻辑。
1、为什么需要垃圾回收?
- 避免内存泄漏:垃圾回收自动检测不再使用的对象,并释放它们占用的内存空间。
- 简化代码:无需手动释放内存,减少了代码中的错误和负担。
2、垃圾回收有哪些特点?
- 自动运行,不需要开发者显性调用
- 当内存不足时触发
- 释放托管内存(即通过.NET内村分配的内存)
- 不保证立即释放内存,而是根据内存压力情况周期性地进行
3、垃圾回收有什么局限性?
- 无法处理非托管资源,如文件句柄、数据库链接、图形设备接口(GDI)对象等
- 可能会导致应用程序出现短暂的暂停(GC暂停)
4、垃圾回收需要注意什么?
- 尽量避免大对象堆:大对象会直接分配到大对象堆,可能会导致垃圾回收器更频繁地工作。
- 适时调用 GC.Collect():虽然大多数情况下不需要手动触发垃圾回收,但在某些特殊场景下,如长时间运行的应用程序,可以考虑适时调用 GC.Collect() 来帮助回收内存。
确定性资源释放
对于非托管资源.NET提供了确定性的资源释放机制,通常通过IDisposable接口实现。
1、使用 using 语句
.NET 提供了 IDisposable 接口来帮助管理非托管资源(例如文件句柄、数据库连接等)。
使用using语句来自动释放实现IDsposable的对象所持有的资源,使用 using 语句可以确保即使在发生异常的情况下也能正确释放资源。
实例中StreamReader实现了IDsposable接口。
通过使用using语句,当StreamReader对象超出作用域时,Dispose方法会被自动调用,从而释放文件句柄。
using System;
using System.IO;
class Program
{
static void Main()
{
using (var stream = new FileStream("demo.txt", FileMode.Open))
{
byte[] buffer = new byte[1024];
int bytesRead = stream.Read(buffer, 0, buffer.Length);
// 处理读取的数据
}
// 文件流会自动关闭
}
}
2、显式调用 Dispose 方法
如果不能使用 using 语句(例如在循环中或其他复杂情况下),可以手动调用 Dispose 方法来释放资源。当一个对象实现了IDsposable接口,意味着它持有需要手动释放的资源,实现IDsposable的对象必须重写Dispose方法来清理非托管缓存。
using System;
using System.IO;
class Program
{
static void Main()
{
FileStream stream = new FileStream("demo.txt", FileMode.Open);
try
{
byte[] buffer = new byte[1024];
int bytesRead = stream.Read(buffer, 0, buffer.Length);
// 处理读取的数据
}
finally
{
stream.Dispose();
}
}
}
总结
好了,我们今天聊了聊 .NET 中的内存管理。通过使用 using 语句和显式调用 Dispose 方法,我们可以更好地控制那些特殊的资源,比如文件和数据库连接。这样不仅能避免程序出错,还能让我们的程序运行得更加顺畅。
如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。
也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

.NET 内存管理两种有效的资源释放方式的更多相关文章
- c#内存管理,垃圾回收和资源释放
<1>关于虚拟内存的概念 Windows使用一个虚拟寻址系统,该系统把程序可用的内存地址映射到硬件内存中的实际地址上去,这些任务完全由windows后台管理,其实际结果是32位处理机上的每 ...
- [Spark内核] 第31课:Spark资源调度分配内幕天机彻底解密:Driver在Cluster模式下的启动、两种不同的资源调度方式源码彻底解析、资源调度内幕总结
本課主題 Master 资源调度的源码鉴赏 [引言部份:你希望读者看完这篇博客后有那些启发.学到什么样的知识点] 更新中...... 资源调度管理 任务调度与资源是通过 DAGScheduler.Ta ...
- Linux 服务管理两种方式service和systemctl
Linux 服务管理两种方式service和systemctl 1.service命令 service命令其实是去/etc/init.d目录下,去执行相关程序 # service命令启动redis脚本 ...
- Linux进程分配内存的两种方式--brk() 和mmap()
如何查看进程发生缺页中断的次数? 用ps -o majflt,minflt -C program命令查看. majflt代表major fault,中文名叫大错误,minflt代表minor faul ...
- 内存分配的原理__进程分配内存有两种方式,分别由两个系统调用完成:brk和mmap(不考虑共享内存)
如何查看进程发生缺页中断的次数? 用ps -o majflt,minflt -C program命令查看. majflt代表major fault,中文名叫大错误,minflt代表minor faul ...
- 进程分配内存的两种方式--brk() 和mmap()(不设计共享内存)(转)
如何查看进程发生缺页中断的次数? 用ps -o majflt,minflt -C program命令查看. majflt代表major fault,中文名叫大错误,minflt代表minor faul ...
- KbmMW两种查询结果集通讯方式
KbmMW本身可以用QueryService的方式进行远程数据查询,但是SmpileService同样具有很强的扩展性可以实现数据查询,下面展示两种基于SmpileService的远程数据查询方法,其 ...
- reportConfig.xml两种数据源连接的配置方式
在reportConfig.xml配置文件中,我们提供了两种数据源连接的配置方式,分别如下: 1.jndi数据源配置(即:在dataSource中配置) 此配置适用于在j2ee的服务器中配置了j ...
- 流式思想概述和两种获取Stream流的方式
流式思想概述 整体来看,流式思想类似于工厂车间的生产流水线 当需要对多个元素进行操作(特别是多步操作)的时候,考虑到性能及便利性,我们应该首先拼好一个模型步骤方案,然后再按照方法去执行他 这张图中展示 ...
- 流思想概述-两种获取Stream流的方式
流思想概述 注意:请暂时忘记对传统IO流的固有印象 ! 整体来看,流式思想类似与工厂车间的 '生产流水线'. 当需要对多个元素进行操作(特别是多步操作)的时候,考虑到性能及便利性,我们应该首先拼好一个 ...
随机推荐
- 【转载】 关于tf.stop_gradient的使用及理解
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/u013745804/article/de ...
- 【转载】 tf.slice()介绍
原文地址: https://blog.csdn.net/nini_coded/article/details/79852031 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议, ...
- Ubuntu 18.04在已经安装Docker CE后如何安装NVIDIA-Docker,以使docker容器内可以使用宿主机显卡
注意: 本文是在电脑上已经安装好docker环境的前提下进行的. docker环境如何安装参照前文. 本文内容节选自: https://baimafujinji.blog.csdn.net/arti ...
- 【官网链接】 REPRODUCIBILITY —— pytorch的可复现性
官网链接地址: https://pytorch.org/docs/stable/notes/randomness.html ====================================== ...
- gym.ActionWrapper使用时的注意点——step函数可以覆盖observation函数
本文说的这个gym.ActionWrapper继承类的问题和gym.ObservationWrapper继承类的问题性质是一样的,具体看: gym.ObservationWrapper使用时的注意点- ...
- 关于mysql配置文件中jdbc url 的记录
版本不同 url不同 大同小异 基本就是不同参数配置的区别 maven 仓库地址 https://mvnrepository.com/artifact/mysql/mysql-connector-ja ...
- bat2exe
https://blog.csdn.net/qq_23452385/article/details/109145151
- Linux内核 自旋锁spin lock,教你如何用自旋锁让ubuntu死锁
背景 由于在多处理器环境中某些资源的有限性,有时需要互斥访问(mutual exclusion),这时候就需要引入锁的概念,只有获取了锁的任务才能够对资源进行访问,由于多线程的核心是CPU的时间分片, ...
- Win32 状态栏用法
WIN32 状态控件用法 1.创建控件 状态栏类名: STATUSCLASSNAME #define STATUSCLASSNAMEW L"msctls_statusbar32 ...
- 异常处理,内置方法(__new__,__init__,__del__析构方法,单例模式,item系列)
__new__ 创建一个对象 class A: def __init__(self): print('in init') def __new__(cls): print('in new') self= ...