在C#中使用线程工具时,如何使用'using'关键字?Dispose方法何时被调用?

3

我正在开发一些控制游戏服务器线程的工具,并尝试使用一个 IDisposable "token",以便我可以使用以下代码:

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

我想获取一个区域中玩家列表的读取锁,使用using块时,当它超出范围时会自动解锁。目前已经实现并运行良好,但我担心调用Dispose()的时间问题。
当程序离开using块时,SyncLock变量是否仅仅被标记为可处理,然后由垃圾回收器在稍后某个时刻清理,还是当前线程在离开using块时执行Dispose()方法?
这种模式基本上是RAII,其中锁是被分配的资源。Jon Skeet在他的MiscUtils中也使用了这种模式(即使用IDisposable "token")。您可以在这里查看此处的示例。
8个回答

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 类似的功能,因为 C# 没有确定性析构函数。


3

Disposeusing范围结束时被调用。这是一个语法糖,相当于:

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

2

Dispose()方法会在using代码块退出时立即被调用。
using在C#中类似于C++中的RAII习惯用法。


1

using文档说明:

using语句确保在调用对象方法时发生异常时也会调用Dispose。您可以通过将对象放置在try块中,然后在finally块中调用Dispose来实现相同的结果;事实上,这就是编译器如何将using语句转换的方式。

因此,是的,一旦退出块,它就被调用了。


1

在 using 块的结尾处会调用 Dispose 方法,因此您应该为 SyncToken 实现 Dispose 方法,以便可以确定地释放 SyncLock,这就是 Dispose 模式的整个意义。


1

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


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收集对象时。没有保证它何时会发生。


0

Dispose方法会在变量超出作用域时立即调用,垃圾回收器将在稍后的某个不确定时间启动,这不会影响Dispose方法的执行。

此外,可以查看以下内容以了解底层发生的简单比较: 使用using和IDisposable


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接