如何在ASMX Web服务中一次将对特定类的访问限制为一个调用者?

时间:2010-04-14 01:11:03

标签: c# .net web-services multithreading asmx

我有一个Web服务方法,我在其中创建一个特定类型的对象,使用它几秒钟,然后处置它。由于多个线程同时创建和使用此类的实例所引起的问题,我需要限制该方法,以便一次只有一个调用者具有这些对象之一。

为此,我正在创建一个私有静态对象:

private static object _lock = new object();

...然后在Web服务方法中,我围绕关键代码执行此操作:

lock (_lock)
{
    using (DangerousObject dob = new DangerousObject())
    {
        dob.MakeABigMess();
        dob.CleanItUp();
    }
}
但是,我不确定这是否有效。我有这个权利吗?此代码是否确保只实例化一个DangerousObject实例并一次使用?或者每个来电者都得到他们自己的_lock副本,让我的代码在这里可笑吗?

来自Ben Voigt回答的链接中的

更新:,我想我需要这样做:

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();
}

这应该与我的lock代码几乎相同,但它将使用全局对象(因为互斥体名称中的“Global \”前缀)。我希望。

3 个答案:

答案 0 :(得分:4)

当然,这取决于你的对象造成的混乱的范围。

每个AppDomain 中只有一个_lock实例。如果您的对象期望对AppDomains之间共享的资源(例如特定文件)进行独占访问,则可能会出现问题。在什么级别应该允许共享访问?通过不同的流程?由不同的用户?决不?这将有助于我们找到解决方案。

编辑:如果您使用静态成员变量来锁定机器全局资源,请害怕,非常害怕。

http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/0e570911-b88e-46be-96eb-a82f737dde5a.mspx?mfr=true

也适用于IIS 7

http://technet.microsoft.com/en-us/library/cc735056(WS.10).aspx

编辑:对于实际的机器范围锁定,请查看System.Threading.Mutex使用LOCAL \或GLOBAL \前缀,具体取决于您是需要每个用户会话还是计算机范围的互斥锁。

编辑:使用try / finally确保Mutex被释放。

答案 1 :(得分:1)

您可能遇到一次发出许多请求并且客户端请求开始超时的问题,因为它们都在等待锁定。您还可能在webfarm场景中遇到问题,其中多个服务器正在处理请求,因此每个服务器都有自己的_lock。我建议改用队列。如果每个客户端都进入并向某个队列添加消息,则单独的服务可以一次一个地处理来自队列的消息,并且客户端不必等待。

答案 2 :(得分:0)

我建议使用Singleton或Factory模式。