开发者

How can I limit access to a particular class to one caller at a time in an ASMX web service?

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.


You could run into problems where many requests are made at once and client requests start timing out as they are all waiting on the lock. You could also run into issues in a webfarm scenario where multiple servers are handling the requests and so each has its own _lock. I would suggest using a queue instead. If each client comes in and adds a message to some queue, then a separate service can process the messages from the queue, one at a time, and the clients will not have to wait.


I would suggest either using a Singleton or a Factory pattern.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜