In my MVC 3 C# application I have some static object that I want to be available to one request at a time. Access to it is only through methods, but I want the lock to be kept in between calling its methods.
Calls will be done only in a controller, usually there will be one or two locked blocks of code.
At first I wanted to expose some static public object and use it simply like
lock(MyClass.lockObject)
{
MyClass.doStuff();
MyClass.doStuff2();
}
, but I find it error prone, as I might forget to lock it somewhere. I wonder if it is a proper way to use Monitor.Enter() in a constructor, and Monitor.Exit() in a Dispose method, and then change my methods to nonstatic? Say, something like:
public class MyClass:IDisposable
{
static protected object _locker = new object();
protected bool isDisposed = false;
public MyClass()
{
Monitor.Enter(_locker);
}
public void Dispose()
{
if (!isDisposed)
{
Monitor.Exit(_locker);
GC.SuppressFinalize(this);
isDisposed = true;
}
}
~SPInstances()
{
Dispose();
}
public void doStuff()
{
if(isDisposed) throw new ObjectDisposedException();
// do stuff here, etc.
}
}
Then I could use it as:
using(MyClass myinstance = new MyClass())
{
myInstance.doStuff();
myInstance.doStuff2();
}
Then, even if I forgot to wrap code in using, it will still lock and there will be some chance that it will get unlocked during garbage collecting…
I’m not proficient in C# and sometimes overlook some aspects, and threading is never easy to debug later on, so I’m wondering if I’m on a good track. Is it a proper way to achieve my goal?
EDIT:
Extending Master Morality idea, would this way be better (I simplified it a bit, as I need only one instance of resource)?
public class MyClass
{
static protected readonly MyResourceType _myResourceStatic = new MyResourceType();
static public void DoWork(Action<MyClass> action)
{
lock(_myResource)
{
action(new MyClass(_myResource));
}
}
protected MyClass(MyResourceType myResource)
{
_myResource = myResource;
}
protected readonly _myResource;
public void DoFirstThing() { ... }
public void DoSecondThing(){ ... }
}
MyClass.DoWork(x =>
{
x.DoFirstThing();
// do unrelated stuff
x.DoSecondThing();
});
IMHO it’s better to
lockinside your own methods. That way, another programmer, or yourself later, doesn’t have to remember tolockbefore they call a method, and it’s simple enough.Later that day…
if you want to be able to call multiple methods with a lock, you can do it with a lambda,
and to be really safe, wrap it in a helper class.