Note that there are some explanatory texts on larger screens.

plurals
  1. POWhat is wrong with this solution to locking and managing locked exceptions?
    primarykey
    data
    text
    <p>My objective is a convention for thread-safe functionality and exception handling within my application. I'm relatively new to the concept of thread management/multithreading. I am using <code>.NET 3.5</code></p> <p>I wrote the following helper method to wrap all my locked actions after reading this article <a href="http://blogs.msdn.com/b/ericlippert/archive/2009/03/06/locks-and-exceptions-do-not-mix.aspx" rel="nofollow noreferrer">http://blogs.msdn.com/b/ericlippert/archive/2009/03/06/locks-and-exceptions-do-not-mix.aspx</a>, which was linked in response to this question, <a href="https://stackoverflow.com/questions/4978850/monitor-vs-lock/4979002#4979002">Monitor vs lock</a>.</p> <p>My thought is that if I use this convention consistently in my application, it will be easier to write thread-safe code and to handle errors within thread safe code without corrupting the state.</p> <pre><code>public static class Locking { private static readonly Dictionary&lt;object,bool&gt; CorruptionStateDictionary = new Dictionary&lt;object, bool&gt;(); private static readonly object CorruptionLock = new object(); public static bool TryLockedAction(object lockObject, Action action, out Exception exception) { if (IsCorrupt(lockObject)) { exception = new LockingException("Cannot execute locked action on a corrupt object."); return false; } exception = null; Monitor.Enter(lockObject); try { action.Invoke(); } catch (Exception ex) { exception = ex; } finally { lock (CorruptionLock) // I don't want to release the lockObject until its corruption-state is updated. // As long as the calling class locks the lockObject via TryLockedAction(), this should work { Monitor.Exit(lockObject); if (exception != null) { if (CorruptionStateDictionary.ContainsKey(lockObject)) { CorruptionStateDictionary[lockObject] = true; } else { CorruptionStateDictionary.Add(lockObject, true); } } } } return exception == null; } public static void Uncorrupt(object corruptLockObject) { if (IsCorrupt(corruptLockObject)) { lock (CorruptionLock) { CorruptionStateDictionary[corruptLockObject] = false; } } else { if(!CorruptionStateDictionary.ContainsKey(corruptLockObject)) { throw new LockingException("Uncorrupt() is not valid on object that have not been corrupted."); } else { // The object has previously been uncorrupted. // My thought is to ignore the call. } } } public static bool IsCorrupt(object lockObject) { lock(CorruptionLock) { return CorruptionStateDictionary.ContainsKey(lockObject) &amp;&amp; CorruptionStateDictionary[lockObject]; } } } </code></pre> <p>I use a LockingException class for ease of debugging.</p> <pre><code> public class LockingException : Exception { public LockingException(string message) : base(message) { } } </code></pre> <p>Here is an example usage class to show how I intend to use this.</p> <pre><code>public class ExampleUsage { private readonly object ExampleLock = new object(); public void ExecuteLockedMethod() { Exception exception; bool valid = Locking.TryLockedAction(ExampleLock, ExecuteMethod, out exception); if (!valid) { bool revalidated = EnsureValidState(); if (revalidated) { Locking.Uncorrupt(ExampleLock); } } } private void ExecuteMethod() { //does something, maybe throws an exception } public bool EnsureValidState() { // code to make sure the state is valid // if there is an exception returns false, return true; } } </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.
 

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