在C#中使用'using'和线程实用程序 - 何时调用Dispose?

时间:2011-06-09 14:07:50

标签: c# multithreading idisposable semaphore

我正在开发一些实用程序来控制游戏服务器的线程,并正在尝试使用IDisposable“令牌”,以便我可以使用这样的代码:

using(SyncToken playerListLock = Area.ReadPlayerList())
{
    //some stuff with the player list here
}

这个想法是我在一个区域中的玩家列表上获得了一个读锁定,并且当它超出使用块的范围时它会自动解锁。到目前为止,这一切都已实施并正在运行,但我担心调用Dispose()的时间。

当程序离开using块时,SyncLock变量是否只是被标记为处置,然后在稍后的某个时候被垃圾收集器清理,或者当前线程是否执行Dispose()方法作为离开using区块的一部分?

这种模式基本上是RAII,其中锁是被分配的资源。 Jon Skeet在他的MiscUtils中使用了这种模式的一个例子(即使用IDisposable“令牌”)here

8 个答案:

答案 0 :(得分:11)

using范围退出后立即清理。

实际上,这个

using(SyncToken playerListLock = Area.ReadPlayerList())
{
    //some stuff with the player list here
}

的语法糖
IDisposable playerListLock;
try {
    playerListLock = Area.ReadPlayerList();
}
finally {
    if (playerListLock != null) playerListLock.Dispose();
}

using的目的是在C#中启用类似RAII的功能,它不具有确定性破坏功能。

答案 1 :(得分:3)

当您退出Dispose的范围时,会调用

using。语法糖:

MyObj instance = null;
try
{
  instance = new MyObj();
}
finally
{
  instance.Dispose();
}

答案 2 :(得分:2)

Dispose()区块退出时,

using被称为immediataly using或多或少是C ++中RAII习语的C#等价物。

答案 3 :(得分:1)

using文档声明:

  

using语句确保了这一点   即使异常,也会调用Dispose   在调用方法时发生   在对象上。你可以实现   通过放置对象得到相同的结果   在try块内,然后调用   在最后一个块中处理;事实上,   这就是using语句的用法   由编译器翻译。

所以是的,只要你退出街区就会被调用。

答案 4 :(得分:1)

在使用块结束时调用Dispose,你应该实现Dispose for SyncToken,以便确定性地释放SyncLock,这是Dispose Pattern的全部要点。

答案 5 :(得分:1)

当您离开using块的范围时,调用Dispose()函数释放已分配的资源,但是SyncToken由它运行的GC wheveher收集。

答案 6 :(得分:1)

using块只是try-finally块的语法糖:

using (var myObject = new MyObject())
{
    ...
}

相当于:

MyObject myObject = null;

try
{
    myObject = new MyObject();
    ...
}
finally
{
    if (myObject != null)
    {
         myObject.Dispose();
    }
}

因此,您确定在退出using区块后,将立即调用Dipose()。

一个完全不同的问题是当GC收集对象时。没有保证何时会发生这种情况。

答案 7 :(得分:0)

一旦变量超出范围,就会调用Dispose方法,垃圾收集器将在稍后的某个未确定点启动并且不会影响它。

另外,看看这个是为了简单比较下面发生的事情: using and IDisposable