开发者

Using 'using' with threading utilities in C# - when is Dispose called?

开发者 https://www.devze.com 2023-03-11 08:33 出处:网络
I am developing some utilities to control threading for a game server and am experimenting with using an IDisposable \"token\" so that I can use code like this:

I am developing some utilities to control threading for a game server and am experimenting with using an IDisposable "token" so that I can use code like this:

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

The idea being that I acquire a read lock on the list of players in an area and it is automatically unlocked when it goes out of scope with the using block. So far this is all impleme开发者_如何转开发nted and working, but I am worried about the timing of the call to Dispose().

Does the SyncLock variable simply get marked for disposal when the program leaves the using block and then get cleaned up by the Garbage Collector at some point later, or does the current thread execute the Dispose() method as a part of leaving the using block?

This pattern is basically RAII, where a lock is the resource being allocated. An example of this pattern (ie, using an IDisposable "token") has also been used by Jon Skeet in his MiscUtils here


It's cleaned up immediately after the using scope exits.

In effect, this

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

is syntactic sugar for

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

The very purpose of using is to enable RAII-like functionality in C#, which doesn't feature deterministic destruction.


Dispose gets called when you exit the scope of the using. Syntactic sugar for:

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


Dispose() is called immediataly when the using block is exited.
using is more or less the C# equivalent of the RAII idiom in C++.


The using docs state that:

The using statement ensures that Dispose is called even if an exception occurs while you are calling methods on the object. You can achieve the same result by putting the object inside a try block and then calling Dispose in a finally block; in fact, this is how the using statement is translated by the compiler.

So yes, it is called as soon as you exit the block.


Dispose gets called at the end of the using block, you should implementation Dispose for SyncToken so that the SyncLock can be released deterministically, this is whole point of the Dispose Pattern.


When you leave the scope of the using block the Dispose() function is called releasing the allocated resource, however the SyncToken is collected by the GC whenether it runs.


using blocks are just a syntactic sugar of a try-finally block:

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

is equivalent to:

MyObject myObject = null;

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

So you have the certainty that Dipose() will be called inmeadiately once you exit the using block.

An alltogether different matter is when the GC collects the object. There is no garantee of when that will happen.


The Dispose method is called as soon as your variable goes out of scope, the garbage collector will kick in at some undetermined point later and doesn't affect this.

Also, have a look at this for a simple comparison of what happens underneath: using and IDisposable

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号