Reputation: 2146
I have a static class which is accessed by multiple threads and uses a ReaderWriterLockSlim in various methods to maintain thread safety. This works fine most of the time, however very intermittently I'm seeing an IOException handle is invalid error being thrown by one particular method as shown in the stack trace below. This has me greatly confused as I didn't even know that System.IO was involved in a ReaderWriterLock.
Any help at all in understanding where the error may be comming from would be greatly appreciated.
Stack Trace:
System.IO.IOException: The handle is invalid.
at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
at System.Threading.EventWaitHandle.Reset()
at System.Threading.ReaderWriterLockSlim.WaitOnEvent(EventWaitHandle waitEvent, UInt32& numWaiters, Int32 millisecondsTimeout)
at System.Threading.ReaderWriterLockSlim.TryEnterUpgradeableReadLock(Int32 millisecondsTimeout)
Code:
class Class1
{
private static ReaderWriterLockSlim readwriteLock = new ReaderWriterLockSlim();
private const int readwriterlocktimeoutms = 5000;
private static void myMethod(int ID)
{
bool IsTaken = false;
bool isWriteLockTaken = false;
if (!readwriteLock.TryEnterUpgradeableReadLock(readwriterlocktimeoutms))
{
throw new Exception("SafeGetSuItem: Error acquiring read lock");
}
else { IsTaken = true; }
try
{
// do some work which may require upgrading to a write lock depending on particular conditions
}
finally
{
if (IsTaken)
{
try
{
readwriteLock.ExitUpgradeableReadLock();
IsTaken = false;
}
catch
{
throw;
}
}
}
}
}
enter code here
bool IsWriteTaken = false;
try
{
if (!readerwriterlock.TryEnterWriteLock(readerwriterlocktimeout))
{
// log the error
}
else
{
IsWriteTaken = true;
}
if (IsWriteTaken)
{
// do some work
}
}
finally
{
if (IsWriteTaken)
{
try
{
readerwriterlock.ExitWriteLock();
}
catch
{
throw;
}
}
}
Upvotes: 3
Views: 709
Reputation: 48949
This is a little weird. You may have stumbled upon a bug in the WaitHandle
class. I picked this apart via Reflector and this is what I am seeing.
Dispose
on the ReaderWriterLockSlim
will call Close
on the EventWaitHandle
listed in the stack trace.Close
on a EventWaitHandle
attempts to dispose the underlying SafeHandle
.Reset
on a EventWaitHandle
calls directly into the ResetEvent
Win32 API from kernel32.dll and passes in the SafeHandle
.SafeHandle
and having that instance consumed by the Win32 API.Are you calling Dispose
on the ReaderWriterLockSlim
instance from another thread while TryEnterUpgradeableReadLock
could be executing? This seems like the most likely scenario to me. Actually, this is the only scenario that I am seeing that would lead to an IOException
being thrown.
It seems to me, based solely on my cursory analysis of the BCL code, that the IOException
could be by-design, but it would make a whole lot more sense if Microsoft could somehow generate a ObjectDisposedException
instead which happens on every single other attempt I have made to reproduce the problem. I would go ahead and report this to Microsoft.
Upvotes: 1