StephenCleary / AsyncEx

A helper library for async/await.
MIT License
3.53k stars 356 forks source link

Dispose design doesn't allow calling it twice. #66

Closed glen-nicol closed 8 years ago

glen-nicol commented 8 years ago

I noticed while using the AsyncReaderWriterLock that if I disposed of a lock twice I got undesirable behavior. Namely that if task1 was waiting on the lock and acquired it after the first call to dispose from task0 the second call to Dispose on task0 would release the task1 lock causing it to:

  1. Not have the lock allowing a taskn to get it and
  2. When dispose is called for that task n -1 then the cycle repeats for the n + 1th owner.

I would like to be able to safely call it twice to write code like this.

using( var wlock = await lock.writerLock())
{
    try{
        await someThingThatCanThrow();
    }catch(SomespecificException)
    {
        wlock.dispose();//called once sometimes
       dosomethingWithoutTheLock();
    }
}//dispose called twice

I looked at the basic AsyncLock class too and it looks like it suffers from the same design flaw. Namely that the Key classes do not check to see if they have been disposed previously before calling into the lock and releasing things.

StephenCleary commented 8 years ago

This is by design in the current implementation, but it will be changed in version 5 to allow multiple Dispose calls. If you want, you can upgrade to the new version of the coordination primitives now. v5 of Nito.AsyncEx will depend on that package.

glen-nicol commented 8 years ago

Good to know. Thanks for the quick reply and great work on the library. Very few gotchas and it is very helpful.