我需要在ManualResetEvent上调用Close()吗?

Kev*_*son 15 c# multithreading dispose resource-leak waithandle

我一直在阅读.NET Threading,并正在研究一些使用ManualResetEvent的代码.我在互联网上找到了很多代码示例.但是,在阅读WaitHandle的文档时,我看到以下内容:

WaitHandle实现了Dispose模式.请参阅实现Finalize和Dispose以清理非托管资源.

没有任何样本似乎在他们创建的ManualResetEvent对象上调用.Close(),甚至是来自pfxteam博客的好的Recursion and Concurrency文章(编辑 - 这有一个我错过的使用块).这只是示例疏忽,还是不需要?我很好奇,因为WaitHandle"封装了特定于操作系统的对象",因此很容易出现资源泄漏.

Kev*_*son 21

我最近转发了一篇摘自C#4.0的Nutshell:The Definitive Reference作者:Joseph Albahari,Ben Albahari.在页834,在第21章:线程中有一节讨论这个.

处理等待句柄

完成等待句柄后,可以调用其Close方法释放操作系统资源.或者,您可以简单地删除对等待句柄的所有引用,并允许垃圾收集器稍后为您完成工作(等待句柄实现处理模式,终结器调用 Close).这是依赖此备份(可以说)可接受的少数情况之一,因为等待句柄具有轻微的操作系统负担(异步委托完全依赖此机制来释放其IAsyncResult的等待句柄).

应用程序域卸载时会自动释放等待句柄.

  • @Djof:即使`WaitHandle`不再有`Finalize`方法,我也不认为这意味着它们会泄漏.相反,清理是在`SafeHandle`中处理的,`WaitHandle`持有一个引用. (5认同)

Sco*_*man 11

通常,如果一个对象实现IDisposable它是出于某种原因这样做,你应该调用Dispose(或者Close,视情况而定).在您的站点示例中,ManualResetEvent包含在一个using语句中,该语句将"自动"处理调用Dispose.在这种情况下,Close是同义词Dispose(在IDisposable提供Close方法的大多数实现中都是如此).

示例中的代码:

using (var mre = new ManualResetEvent(false))
{
   ...
}
Run Code Online (Sandbox Code Playgroud)

扩展到

var mre = new ManualResetEvent(false);
try
{
   ...
}
finally
{
   ((IDispoable)mre).Dispose();
}
Run Code Online (Sandbox Code Playgroud)