什么时候应该显式调用System.Threading.Timer的Dispose()函数?

vaprant 2016-07-15 11:35:11
如题:
1、用完一个System.Threading.Timer后,是否一定要调用Dispose()函数释放资源?如果不调用,系统会自动释放吗?

2、如何判断一个对象是否拥有非托管资源(是托管资源还是非托管资源),如何判断一个对象一定要手动调用Dispose()?

3、MSDN上说,Component 应通过调用其 Dispose 方法来显式释放资源,这是为什么?Component 是一个托管资源,为啥需要显式释放资源?

谢谢!
...全文
223 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
vaprant 2016-07-18
  • 打赏
  • 举报
回复
引用 2 楼 sp1234 的回复:
1. 不是“一定要”。系统当然会释放掉它。 2. 没有什么接口说明对象“是否拥有非托管资源。拥有非托管资源也并不是说一定要“手动调用Dispose()”。 必须调用 Dispose 的情况很少,分别由不同的原因。如果你能举出实例来看看分别是什么原因,就明白了。如果想空洞地说这个“规则”,那么可以说并没有什么固定的规则。 基本来说,所有对象早晚都会在 GC 销毁它之前调用 Dispose 方法。在 .net 类库中大量类型的 Dispose 方法中写了 GC.SuppressFinalize代码,防止重复调用 Dispose 方法(因为其对系统性能有影响)。你要么不惜占用程序运行时键而手动调用它、但是写 GC.SuppressFinalize,要么就不要调用 Dispose 而让程序把时间花在正经代码执行上(因为反正系统会在 GC 回收对象之前调用 Dispose)。 比如说你写完一个文件,如果你考虑到这个文件可能立即需要被其它操作读,那么你要不惜花费时间代价,立刻释放它(对文件对象调用Close 跟调用 Dispose 是一样的意思)。而你并不有这个需求时,就不需要立刻调用 Dispose。 3. 请具体给出内容链接。假设 msdn 上说的 Compoment 是指跨进程通讯框架中的 Compoment,而你把它理解为其它许多种命名空间中的 Compoment 之一,那你就是太不应该了。
谢谢,还是有些疑惑? 3、我所说的Compoment 是指:System.ComponentModel.Component。 4、例如我的类中有一个成员是System.Threading.Timer,我是否应在类的析构函数中调用Timer.Dispose()方法,或是在我的类中实现MSDN推荐的Dispose模式? 5、如果我的类中有FileStream成员,是否需要在析构函数中调用FileStream的Dispose方法?
sp1234_maJia 2016-07-16
  • 打赏
  • 举报
回复
关于“并且调用析构函数的时候肯定要调用dispose”,我来补充一下,假设你开发的UI 组件是从标准的组件父类继承的,那么标准的组件父类在 Finalize 函数或者析构函数(二者只需要具有其一)就去调用 Dispose 方法。 因此实际上 Dispose 会被反复调用许多次,是一个容易比较“乱”的机制。但是一时也没有什么好办法减少调用它的次数。 反过来说,GC释放对象其实是很复杂的,它分成许多个阶段,它会先释放那些没有终结器的简单对象,然后等有空闲时间了才会释放那些“看起来”非常释放起来耗时的对象。因此 Dispose 又会被推迟很久之后才被调用。终结器执行时一旦出现bug,进程就会崩溃,程序就会直接停掉了。 如果你需要立即调用 Dispose,通常,是需要“提前”调用它以避免程序抛出共享资源“用尽”的异常,或者“不调用它就会造成进程崩溃”。
  • 打赏
  • 举报
回复
当你认为“一定要调用 Dispose方法”时,要去具体查看文档,看看它是以什么理由。 你会看到,那种“凡是用到非托管资源,就一定要手动调用 Dispose”的说法是站不住脚的。只不过需要手动释放的许多对象类型都使用到了非托管资源,就好像许多中国人都到过非洲某些国家、回来后都需要抽血检查一下有没有特种病毒。但是不是说从非洲回来的人不经验血直接关到医院里几个月。因此这个说法说明其担忧,但是没有说明真正的技术原因!
  • 打赏
  • 举报
回复
自己写的代码,通常在实现了 IDisposeable 接口时懒得写 GC.SuppressFinalize 代码的。这是一个通病。 在功能上,不写它通常也不会测试出任何 bug。但是实际上 GC 销毁对象之前或许会在调用 Dispose 时“卡一下”,但是我们在测试时并不知道这个性能代价。 因此一个类型如果其 Dispose 方法中不调用 GC.SuppressFinalize 的危害有多大,恐怕只有 .net 系统开发人员才清楚。而我们通常并不清楚。我们的习惯上不写 GC.SuppressFinalize。
  • 打赏
  • 举报
回复
1. 不是“一定要”。系统当然会释放掉它。 2. 没有什么接口说明对象“是否拥有非托管资源。拥有非托管资源也并不是说一定要“手动调用Dispose()”。 必须调用 Dispose 的情况很少,分别由不同的原因。如果你能举出实例来看看分别是什么原因,就明白了。如果想空洞地说这个“规则”,那么可以说并没有什么固定的规则。 基本来说,所有对象早晚都会在 GC 销毁它之前调用 Dispose 方法。在 .net 类库中大量类型的 Dispose 方法中写了 GC.SuppressFinalize代码,防止重复调用 Dispose 方法(因为其对系统性能有影响)。你要么不惜占用程序运行时键而手动调用它、但是写 GC.SuppressFinalize,要么就不要调用 Dispose 而让程序把时间花在正经代码执行上(因为反正系统会在 GC 回收对象之前调用 Dispose)。 比如说你写完一个文件,如果你考虑到这个文件可能立即需要被其它操作读,那么你要不惜花费时间代价,立刻释放它(对文件对象调用Close 跟调用 Dispose 是一样的意思)。而你并不有这个需求时,就不需要立刻调用 Dispose。 3. 请具体给出内容链接。假设 msdn 上说的 Compoment 是指跨进程通讯框架中的 Compoment,而你把它理解为其它许多种命名空间中的 Compoment 之一,那你就是太不应该了。
threenewbee 2016-07-16
  • 打赏
  • 举报
回复
对于系统类库来说,编写了dispose方法,就说明这个对象肯定是有非托管资源的。并且调用析构函数的时候肯定要调用dispose 对于非系统类库,一些开发者可能不会按照这个规则去写,这要看源代码。 如果你希望非托管资源用完就释放(因为自动垃圾回收不一定立刻执行),那么就要调用dispose

110,534

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧