I have a web service method in which I create a particular type of object, use it for a few seconds, and then dispose it. Because of problems arising from multiple threads creating and using instances of this class at the same time, I need to restrict the method so that only one caller at a time ever has one of these objects.
To do this, I am creating a private static object:
private static object _lock = new object();
… and then inside the web service method I do this around the critical code:
lock (_lock)
{
using (DangerousObject dob = new DangerousObject())
{
dob.MakeABigMess();
dob.CleanItUp();
}
}
I’m not sure this is working, though. Do I have this right? Will this code ensure that only one instance of DangerousObject is instantiated and in use at a time? Or does each caller get their own copy of _lock, rendering my code here laughable?
Update: from a link in Ben Voigt’s answer, I think I need to do this instead:
Mutex m = new Mutex(false, @"Global\MyMutex");
m.WaitOne();
try
{
using (DangerousObject dob = new DangerousObject())
{
dob.MakeABigMess();
dob.CleanItUp();
}
}
catch (Exception ex)
{
// what could possibly go wrong?
}
finally
{
m.ReleaseMutex();
}
This should function pretty much the same as my lock code, but it will instead use a global object (because of the “Global\” prefix in the mutex’ name). I hope.
It depends on the scope of the mess your object makes, of course.
There will be only one instance of _lock in each AppDomain. If your object expects exclusive access to a resource shared between AppDomains, such as a particular file, this might be trouble. At what level should shared access be allowed? By different processes? By different users? Never? That will help us find you a solution.
EDIT: Be afraid, be very afraid, if you’re using static member variables to lock machine-global resources.
http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/0e570911-b88e-46be-96eb-a82f737dde5a.mspx?mfr=true
Applies to IIS 7 as well
http://technet.microsoft.com/en-us/library/cc735056(WS.10).aspx
EDIT: For an actual machine-wide lock, have a look at System.Threading.Mutex Use either the LOCAL\ or GLOBAL\ prefix depending on whether you want one mutex per user session or computer-wide.
EDIT: Use a try/finally to make sure the Mutex gets released.