简体   繁体   中英

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 . 只有一个_lock实例。 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.

我建议使用Singleton或Factory模式。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM