Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <ol> <li>Move the IsCorrupt test and the Monitor.Enter inside the Try </li> <li>Move the corruption set handling out of finally and into the Catch block (this should only execute if an exception has been thrown)</li> <li>Don't release the primary lock until after the corruption flag has been set (leave it in the finaly block)</li> <li>Don't restrict the execption to the calling thread; either rethow it or add it to the coruption dictionary by replacing the bool with the custom execption, and return it with the IsCorrupt Check</li> <li>For Uncorrupt simply remove the item</li> <li>There are some issues with the locking sequencing (see below)</li> </ol> <p>That should cover all the bases</p> <pre><code> public static class Locking { private static readonly Dictionary&lt;object, Exception&gt; CorruptionStateDictionary = new Dictionary&lt;object, Exception&gt;(); private static readonly object CorruptionLock = new object(); public static bool TryLockedAction(object lockObject, Action action, out Exception exception) { var lockTaken = false; exception = null; try { Monitor.Enter(lockObject, ref lockTaken); if (IsCorrupt(lockObject)) { exception = new LockingException("Cannot execute locked action on a corrupt object."); return false; } action.Invoke(); } catch (Exception ex) { var corruptionLockTaken = false; exception = ex; try { Monitor.Enter(CorruptionLock, ref corruptionLockTaken); if (CorruptionStateDictionary.ContainsKey(lockObject)) { CorruptionStateDictionary[lockObject] = ex; } else { CorruptionStateDictionary.Add(lockObject, ex); } } finally { if (corruptionLockTaken) { Monitor.Exit(CorruptionLock); } } } finally { if (lockTaken) { Monitor.Exit(lockObject); } } return exception == null; } public static void Uncorrupt(object corruptLockObject) { var lockTaken = false; try { Monitor.Enter(CorruptionLock, ref lockTaken); if (IsCorrupt(corruptLockObject)) { { CorruptionStateDictionary.Remove(corruptLockObject); } } } finally { if (lockTaken) { Monitor.Exit(CorruptionLock); } } } public static bool IsCorrupt(object lockObject) { Exception ex = null; return IsCorrupt(lockObject, out ex); } public static bool IsCorrupt(object lockObject, out Exception ex) { var lockTaken = false; ex = null; try { Monitor.Enter(CorruptionLock, ref lockTaken); if (CorruptionStateDictionary.ContainsKey(lockObject)) { ex = CorruptionStateDictionary[lockObject]; } return CorruptionStateDictionary.ContainsKey(lockObject); } finally { if (lockTaken) { Monitor.Exit(CorruptionLock); } } } } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload