ReaderWriteLockSlim抛出IOException?

时间:2011-06-02 17:54:35

标签: c# multithreading

我有一个静态类,可以被多个线程访问,并在各种方法中使用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;
                }
            }
        }

1 个答案:

答案 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而不是我为重现问题所做的每一次其他尝试。我会继续向微软报告。

相关问题