我有一个静态类,可以被多个线程访问,并在各种方法中使用ReaderWriterLockSlim来维护线程安全。这在大多数情况下工作正常,但非常间歇性地我看到IOException句柄是由一个特定方法抛出的无效错误,如下面的堆栈跟踪所示。这让我非常困惑,因为我甚至不知道System.IO参与了ReaderWriterLock。
在理解错误可能来自哪里时,任何帮助都将非常感激。
堆栈追踪:
System.IO.IOException:句柄无效 在System.IO .__ Error.WinIOError(Int32 errorCode,String maybeFullPath)
在System.Threading.EventWaitHandle.Reset()
在System.Threading.ReaderWriterLockSlim.WaitOnEvent(EventWaitHandle waitEvent,UInt32& numWaiters,Int32 millisecondsTimeout)
在System.Threading.ReaderWriterLockSlim.TryEnterUpgradeableReadLock(Int32 millisecondsTimeout)
代码:
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;
}
}
}
答案 0 :(得分:1)
这有点奇怪。您可能偶然发现了WaitHandle
课程中的错误。我通过Reflector选择了这个,这就是我所看到的。
Dispose
上的ReaderWriterLockSlim
将致电堆栈跟踪中列出的Close
上的EventWaitHandle
。Close
上调用EventWaitHandle
尝试处置基础SafeHandle
。Reset
调用EventWaitHandle
直接从kernel32.dll调用ResetEvent
Win32 API并传入SafeHandle
。SafeHandle
和让Win32 API使用该实例之间的竞争。在Dispose
执行时,您是否正在从另一个线程调用ReaderWriterLockSlim
实例上的TryEnterUpgradeableReadLock
?这对我来说似乎是最可能发生的情况。实际上,这是我看到的唯一会导致IOException
被抛出的情况。
在我看来,完全基于我对BCL代码的粗略分析,IOException
可能是按设计进行的,但如果微软认为它会更有意义可能会以某种方式生成ObjectDisposedException
而不是我为重现问题所做的每一次其他尝试。我会继续向微软报告。