I am writing an application that makes extensive use of multithreading. Some of the threads share an observable collection using ReaderWriterLockSlim.
I get a dead end from time to time, and I need to know which thread holds the lock at the time of the dead end. How can I know this? I looked at the properties of the object, and there was nothing obvious. Currently, all I know is which threads are waiting for a lock.
Thank you for your help!
EDIT: Of course, I'm talking about finding it during debugging with all the debugging information available.
, , , .
, readerwriterlockslim .
, , , , . , . , (Breakpoint → When Hit...) , - .
ReaderWriterLockSlim , . , , . , EnterReadLockDebug ExitReadLockDebug , EnterReadLock ExitReadLock , . , . , , .
ReaderWriterLockSlim
EnterReadLockDebug
ExitReadLockDebug
EnterReadLock
ExitReadLock
, . Debug vs. Release , . , Debug , , Release .
., , , "Enter" .
public class ReaderWriterLockSlimExtended : ReaderWriterLockSlim { private Thread m_currentOwnerThread = null; private object m_syncRoot = new object(); public Thread CurrentOwnerThread { get { lock (m_syncRoot) { return m_currentOwnerThread; } } } public Thread CurrentOwnerThreadUnsafe { get { return m_currentOwnerThread; } } public new void EnterWriteLock() { lock (m_syncRoot) { base.EnterWriteLock(); m_currentOwnerThread = Thread.CurrentThread; } Debug.WriteLine("Enter Write Lock - Current Thread : {0} ({1})", CurrentOwnerThread.Name, CurrentOwnerThread.ManagedThreadId); } public new void ExitWriteLock() { Debug.WriteLine("Exit Write Lock - Current Thread : {0} ({1})", CurrentOwnerThread.Name, CurrentOwnerThread.ManagedThreadId); lock (m_syncRoot) { m_currentOwnerThread = null; //Must be null before exit! base.ExitWriteLock(); } } }
, , :
using System; using System.Threading; namespace Utils { public class ReaderWriterLockSlim2 { #region Attributes private readonly TimeSpan _maxWait; private readonly ReaderWriterLockSlim _lock; #endregion #region Properties public int CurrentWriteOwnerId { get; private set; } public string CurrentWriteOwnerName { get; private set; } #endregion #region Public Methods public ReaderWriterLockSlim2(LockRecursionPolicy policy, TimeSpan maxWait) { _maxWait = maxWait; _lock = new ReaderWriterLockSlim(policy); } public void EnterWriteLock() { if (!_lock.TryEnterWriteLock(_maxWait)) { throw new TimeoutException(string.Format("Timeout while waiting to enter a WriteLock. Lock adquired by Id {0} - Name {1}", this.CurrentWriteOwnerId, this.CurrentWriteOwnerName)); } else { this.CurrentWriteOwnerId = Thread.CurrentThread.ManagedThreadId; this.CurrentWriteOwnerName = Thread.CurrentThread.Name; } } public void ExitWriteLock() { _lock.ExitWriteLock(); this.CurrentWriteOwnerId = 0; this.CurrentWriteOwnerName = null; } public void EnterReadLock() { _lock.EnterReadLock(); } public void ExitReadLock() { _lock.ExitReadLock(); } #endregion } }