The motive was a lot of race conditions and deadlocks that happened to my team members so i found a solution for them by enforcing all the reading and writing to our model to be thread safe.
This is how i implemented it:
using System; using System.Threading; namespace MyCode { public class ThreadSafeObject<T>{ private readonly ReaderWriterLockSlim _rwLock; private T _value; public ThreadSafeObject(T value){ _rwLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); _value = value; } public void SafeRead(Action<T> readFunction){ try{ _rwLock.EnterReadLock(); readFunction.Invoke(_value); } finally{ _rwLock.ExitReadLock(); } } public void SafeWrite(Action<T> writeFunction){ try{ _rwLock.EnterWriteLock(); writeFunction.Invoke(_value); } finally{ _rwLock.ExitWriteLock(); } } } }
So as you can see, any access to my model (T) must go through a loch (read or write).
In our team, the T also implements an 'Observable' pattern so if a 'write' action is made inside read lock i actually throw 'IllegalOperationException' and also enforce that no write is performed in read lock.
Here is some code example of how to use it:
namespace MyCode { class Model { public int IntValue { get; set; } public string StringValue { get; set; } } class Example { public void ThreadSafeExample() { var threadSafeObject = new ThreadSafeObject<Model>(new Model()); /// Writing values in a safe single transaction threadSafeObject.SafeWrite(state => { state.IntValue = 100; state.StringValue = "This is very cool design!!"; }); /// Reading values in a safe way (allow also multiple readers) var intValueRead = 0; var stringValueRead = string.Empty; var readingTime = DateTime.MinValue; threadSafeObject.SafeRead(state => { readingTime = DateTime.Now; intValueRead = state.IntValue; stringValueRead = state.StringValue; }); Console.WriteLine("At {0} the model had in value of {1} and string value of: {2}", readingTime, intValueRead, stringValueRead); } } }
This is it...
I hope it will be helpful for you as it was for me.
Gur