在 C# 中将'using'与线程实用程序一起使用 - 何时调用 Dispose?



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

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

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

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

这种模式基本上是RAII,其中锁是正在分配的资源。Jon Skeet在他的MiscUtils here

中也使用了这种模式的一个例子(即使用IDisposable"令牌")

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的功能,它不具有确定性破坏的特点。

当您退出using的作用域时,会调用

Dispose。的合成糖

MyObj instance = null;
try
{
  instance = new MyObj();
}
finally
{
  instance.Dispose();
}
using块退出时,

Dispose()被立即调用
using或多或少是C++中RAII习语的C#等价物。

using文档声明:

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

所以,是的,只要你离开区块,它就会被调用。

Dispose在using块结束时被调用,您应该为SyncToken实现Dispose,这样SyncLock就可以被决定性地释放,这就是Dispose模式的全部意义。

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

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

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

相当于:

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

因此,您可以确定,一旦您退出using块,Dipose()将首先被调用。

一个完全不同的事情是当GC收集对象时。不知道什么时候会发生。

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

此外,请查看以下内容,以便对下面发生的情况进行简单比较:使用和IDisposable

最新更新