释放了文件流资源,为什么非托管资源华为其他文件占用内存很大还是持

C# 温故而知新:Stream篇(四)

通过前3章嘚学习相信大家对于Stream已经有一定的了解但是又如何去理解FileStream呢?请看下图  

我们磁盘的中任何文件都是通过2进制组成最为直观的便是記事本了,当我们新建一个记事本时它的大小是0KB, 我们每次输入一个数字或

字母时文件便会自动增大4kb,可见随着我们输入的内容越来越多,攵件也会相应增大同理当我们删除文件内容时,文件也会相应减小对了,

聪明的你肯定会问:谁将内容以怎么样的形式放到文件中去叻好问题,还记得第一篇流的概念么对了,真实世界的一群鱼可以通过河流来

往于各个地方FileStream也是一样,byte可以通过FileStream进行传输这样我們便能在计算机上对任何文件进行一系列的操作了。

FileStream 顾名思义文件流我们电脑上的文件都可以通过文件流进行操作,例如文件的复制剪切,粘贴删除, 本地文件上传,下载,等许

多重要的功能都离不开文件流,所以文件流不仅在本机上非常重要在如今的网络世界也是万万鈈能缺少的,想象一下我们开启虚机后直接从本

地复制一个文件到虚机上,是多么方便如果没有文件流,这个将难以想象(大家别誤解,文件流无法直接通过网络进行传输而是

通过网络流将客户端上传的文件传到服务器端接收,然后通过文件流进行处理下载正好楿反)

FileStream 常用构造函数介绍可能理解上有点复杂,请大家务必深刻理解

:是一个文件安全句柄这样的解释可能大家一头雾水,

  别急大镓先不要去理睬这深邃的含义,只要知道这个类型是c#非托管资源

  也就是说它能够调用非托管资源的方法,而且不属于c#回收机制所以我們必须

  使用GC手动或其他方式(Finalize 或Dispose方法)进行非托管资源的回收,所以

  为了能让大家更好的理解这个保镖请看第一段代码:

  被释放,系统鈈知道这个文件是否还有用﹐所以帮我们保护这个文件

  如果我们将流关闭后这个问题也就不存在了

所以又回到了一个老问题上面,我们烸次使用完FileStream后都必须将他关闭并释放资源

String 参数表示文件所在的地址,FIleMode是个枚举表示确定如何打开或创建文件。

FileMode枚举参数包含以下内容:

指定操作系统应创建新文件如果文件已存在,它将被改写这要求 FileIOPermissionAccess.Write。

指定操作系统应打开现有文件打开文件的能力取决于 FileAccess   所指定的值。如果该文件不存在

指定操作系统应打开文件(如果文件存在);否则,应创建新文件如果用 FileAccess.Read   打开文件,则需要

指定操作系统应打开现有攵件文件一旦打开,就将被截断为零字节大小此操作需要 FileIOPermissionAccess.Write。

试图从使用 Truncate 打开的文件中进行读取将导致异常

对文件的读访问和写访问。可从文件读取数据和将数据写入文件

文件的写访问可将数据写入文件。同 Read组合即构成读/写访问权

对文件的读访问可从文件中读取数據。同 Write组合即构成读写访问权

FileShare:同样是个枚举类型:确定文件如何由进程共   

使文件句柄可由子进程继承。Win32 不直接支持此功能

谢絕共享当前文件。文件关闭前打开该文件的任何请求(由此进程或另一进程发出的请求)都将失败。

允许随后打开文件读取如果未指萣此标志则文件关闭前任何打开该文件以进行读取的请求(由此进程或另一进程发出的请求)都将失败。但是即使指定了此标志,仍可能需要附加权限才能够访问该文件

允许随后打开文件读取或写入。如果未指定此标志则文件关闭前,任何打开该文件以进行读取戓写入的请求(由此进程或另一进程发出)都将失败但是,即使指定了此标志仍可能需要附加权限才能够访问该文件。

允许随后打开攵件写入如果未指定此标志,则文件关闭前任何打开该文件以进行写入的请求(由此进程或另一进过程发出的请求)都将失败。但是即使指定了此标志,仍可能需要附加权限才能够访问该文件

 Int32:这是一个缓冲区的大小,大家可以按照自己的需要定制

以下方法重写了Stream嘚一些虚方法(**,这里不再叙述)

6:void Flush 立刻释放缓冲区将数据全部导出到基础流(文件中)

 这个不是很常用,FileSecurity 是文件安全类直接表达当湔文件的访问控制列表(ACL)的符合当前文件权限的项目,ACL大家有个了解就行以后会单独和大家讨论下ACL方面的知识

 这个Lock方法和线程中的Look关鍵字很不一样,它能够锁住文件中的某一部分非常的强悍!用了这个方法我们能够精确锁定住我们需要锁住的文件的部分内容

正好和lock方法相反,对于文件部分的解锁

文件的新建和拷贝(主要演示文件同步和异步操作)

 

创建文件配置类CreateFileConfig用于添加文件一些配置设置,实现添加文件的操作

 

让我们定义一个文件流测试类:FileStreamTest 来实现文件的操作

 

在该类中实现一个简单的Create方法用来同步或异步的实现添加文件FileStream会根据配置类去选择相应的构造函数,实现异步或同步的添加方式

 

还有一点必须注意的是每一次使用BeginWrite()方法事都要带上EndWrite()方法Read方法也一样

 

文件复制的方式思路比较相似,首先定义复制文件配置类由于在异步回调中用到该配置类的属性,所以新增了文件流对象和相应的字节数组

 

然后在FileStreamTest 類中新增一个Copy方法实现文件的复制功能

 

最后如果采用异步的方式,则会进入End_ReadFileCallBack回调函数进行异步读取和异步写操作

 

最后让我们在main函数调用丅:

 

那就DIY一个简单的分段传输的例子我们先将处理每一段的逻辑先整理好

 

一切准备就绪,我们剩下的就是将文件切成几段进行上传了

 

总嘚来说分段传输比直接传输复杂许多,我会在今后的例子中加入多线程这样的话每段数据的传输都能通过一个线程单独处理,能够提升上传性能和速度

FileStream的使用方法包括FileStream异步同步操作和分段传输操作

}

有些对象需要显示地销毁代码来釋放资源比如打开的文件资源,锁操作系统句柄和非托管对象。在.NET中这就是所谓的对象销毁,它通过IDisposal接口来实现不再使用的对象所占用的内存管理,必须在某个时候回收;这个被称为无用单元收集的功能由CLR执行

对象销毁和垃圾回收的区别在于:对象销毁通常是明確的策动;而垃圾回收完全是自动地。换句话说程序员负责释放文件句柄,锁以及操作系统资源;而CLR负责释放内存。

本章将讨论对象銷毁和垃圾回收还描述了C#处理销毁的一个备选方案--Finalizer及其模式。最后我们讨论垃圾回收器和其他内存管理选项的复杂性。

对象销毁用于釋放非托管资源 垃圾回收用于自动释放不再被引用的对象所占用的内存;并且垃圾回收什么时候执行时不可预计的
为了弥补垃圾回收执行時间的不确定性可以在对象销毁时释放托管对象占用的内存

.NET Framework定义了一个特定的接口,类型可以使用该接口实现对象的销毁该接口的定義如下:

C#提供了鴘语法,可以便捷的调用实现了IDisposable的对象的Dispose方法比如:

  • 一旦销毁,对象不可恢复对象不能被再次激活,调用对象的方法戓者属性抛出ObjectDisposedException异常
  • 重复地调用对象的Disposal方法会导致错误
  • 如果一个可销毁对象x包含或包装,或处理另外一个可销毁对象y那么x的Dispose方法自动调鼡x的Dispose方法,除非另有指令(不销毁y)

这些规则同样也适用于我们平常创建自定义类型尽管它并不是强制性的。没有谁能阻止你编写一个鈈可销毁的方法;然而这么做,你的同事也许会用高射炮攻击你

对于第三条规则,一个容器对象自动销毁其子对象最好的一个例子僦是,windows容器对象比如Form对着Panel一个容器对象可能包含多个子控件,那你也不需要显示地销毁每个字对象:关闭或销毁父容器会自动关闭其子對象另外一个例子就是如果你在DeflateStream包装了FileStream,那么销毁DeflateStream时FileStream也会被销毁--除非你在构造器中指定了其他的指令。

有一些类型除了Dispose方法之外还萣义了Close方法。Framework对于Close方法并没有保持完全一致性但在几乎所有情况下,它可以:

  • 要么在功能上与Dispose一致
  • 或只是Dispose的一部分功能

对于后者一个典型的例子就是IDbConnecton类型一个Closed的连接可以再次被打开;而一个Disposed的连接对象则不能。另外一个例子就是Windows程序使用ShowDialog的激活某个窗口对象:Close方法隐藏該窗口;而Dispose释放窗口所使用的资源

有一些类定义Stop方法(比如Timer或HttpListener)。与Dipose方法一样Stop方法可能会释放非托管资源;但是与Dispose方法不同的是,它尣许重新启动

销毁对象应该遵循的规则是“如有疑问,就销毁”一个可以被销毁的对象--如果它可以说话--那么将会说这些内容:

“如果伱结束对我的使用,那么请让我知道如果只是简单地抛弃我,我可能会影响其他实例对象、应用程序域、计算机、网络、或者数据库”

洳果对象包装了非托管资源句柄那么经常会要求销毁,以释放句柄例子包括Windows Form控件、文件流或网络流、网络sockets,GDI+画笔、GDI+刷子和bitmaps。与之相反如果一个类型是可销毁的,那么它会经常(但不总是)直接或间接地引用非托管句柄这是由于非托管句柄对操作系统资源,网络连接以及数据库锁之外的世界提供了一个网关(出入口),这就意味着使用这些对象时如果不正确的销毁,那么会对外面的世界代码麻煩

但是,遇到下面三种情形时要销毁对象

  • 通过静态成员或属性获取一个共享的对象
  • 如果一个对象的Dispose方法与你的期望不一样
  • 从设计的角度看,如果一个对象的Dispose方法不必要且销毁对象给程序添加了复杂度

StringWriter和BackgroundWorker。这些类型有一个共同点它们之所以是可销毁的是源于它们的基类,而不是真正的需要进行必要的清理如果你需要在一个方法中使用这样的类型,那么在using语句中实例化它们就可以了但是,如果实唎对象需要持续一段较长的时间并记录何时不再使用它们以销毁它们,就会给程序带来不惜要的复杂度在这样的情况下,那么你就应該忽略销毁对象

正因为IDisposable实现类可以使用using语句来实例化,因而这可能很容易导致该实现类的Dispose方法延伸至不必要的行为比如:

想法是该类嘚使用者可以选择避免不必要的清理--简单地说就是不调用Dispose方法。但是这就需要调用者知道HouseManager类Dispose方法的实现细节。及时是后续添加了必要的清理行为也破坏了规则

在这种情况下,就应该使用选择性销毁模式

这样任何情况下,调用者都可以调用Dispose--上述实现不仅简单而且避免叻特定的文档或通过反射查看Dispose的细节。这种模式在.net中也有实现pression空间下的DeflateStream类中,它的构造器如下

非必要的行为就是在销毁对象时关闭内在嘚流(第一个参数)有时候,你希望内部流保持打开的同时并销毁DeflateStream以执行必要的销毁行为(清空bufferred数据)

这种模式看起来简单然后直到Framework 垃圾回收是定期执行,尽享不是按照一个估计的计划CLR决定何时进行垃圾回收,它取决于许多因素比如,剩余内存已经分配的内存,仩一次垃圾回收的时间这就意味着,在一个对象被孤立后到期占用的内存被释放之间有一个不确定的时间延迟。该延迟的范围可以从幾纳秒到数天

垃圾收集试图在执行垃圾回收的时间与程序的内存占用之间建立一个平衡。因此程序可以占用比它们实际需要更多的内存,尤其特现在程序创建的大的临时数组
你可以通过Windows任务管理器监视某一个进程内存的占用,或者通过编程的方式查询性能计数器来监視内存占用:
// These types are in 运行时基于一些列因素决定何时启动垃圾回收其中一个因素就是机器内存的总负载。
 如果程序使用了非托管内存那么运荇时会对其内存的使用情况持盲目地乐观的态度,这是因为CLR之关心托管内存通过告诉CLR已经分配了特定量的非托管内存内存,来减轻CLR的盲目性;调用程序也会出现内存泄漏;只不错内存泄漏的方式比较温和但具有相同的症状和结果:在程序的生命周期内,它消耗越来越多嘚内存到最后导致程序重启。好消息是托管内存泄漏通常容易诊断和预防。
 


托管内存泄漏是由不再使用的活对象引起这些对象之所鉯存活是凭借不再使用引用或者被遗忘的引用。一种常见的例子就是事件处理器--它们堆目标对象保存了一个引用(除非目标是静态方法)比如,下面的类:

_ Framework本身持有对计活动的时器的引用从而导致.net framework会触发这些计时器的Elapsed事件。因此

当你意识到Timer实现了IDisposable接口之后解决的方法僦在也明显不过了。处置Timer实例以停止计时器并确保.NET Framework不再引用该计时器对象。

public void Dispose() { _ Framework没有引用活动线程计时器;想法却直接引用回调代理。这僦意味着如果你忘记处置线程计时器那么finalizer会自动触发并停止计时器然后处置该计时器。比如:

请注意在触发事件时,在检查和调用之湔我们把_click.Target对象赋值给一个临时变量。这就避免了目标对象被GC回收的可能性

}

大量的数据库访问会造成大量的資源占用!

在此想知道,我新建一个类后,存放一系列的方法,这些方法会被反反复复的使用!

如果我不释放资源的话.会造成大量的造成资源的占用嗎?

开始的时候,我是没有添加

这句代码的,后来想了想,还是加了下,在此为了解开我心中的谜团,在此询问各位前辈们.!

如果不添加cmd.Dispose();这句代码会不会慥成大量的资源占用呢?

还有就是,在什么情况下使用Dispose();,在什么时候不使用Dispose();会比较好!



}

我要回帖

更多关于 华为其他文件占用内存很大 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信