我有一个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 \”前缀)。我希望。
答案 0 :(得分:4)
当然,这取决于你的对象造成的混乱的范围。
每个AppDomain 中只有一个_lock实例。如果您的对象期望对AppDomains之间共享的资源(例如特定文件)进行独占访问,则可能会出现问题。在什么级别应该允许共享访问?通过不同的流程?由不同的用户?决不?这将有助于我们找到解决方案。
编辑:如果您使用静态成员变量来锁定机器全局资源,请害怕,非常害怕。也适用于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模式。