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