我有一个asmx web服务,只允许一次响应1个客户端。
换句话说,如果服务被客户端A调用,而服务器B调用,我希望B挂起,直到A完成,然后B才能得到服务。
如果这太复杂了,那么在A参与服务的过程中,来自B的最低限度的呼叫将失败,并显示用户定义的错误。
原因是该服务在很大程度上依赖于IO操作和XML序列化,因此至关重要的是该服务不会被多个客户端同时调用。
提前致谢
答案 0 :(得分:4)
static object _LockObject = new object();
void WebServiceCall()
{
lock(_LockObject)
{
// Do work...
}
}
创建一个名为lock()的静态对象。 lock()
语句将阻止其他调用执行代码,直到第一次执行锁定完成。
请注意,根据您的超时设置,B可能会因超时而失败,具体取决于A完成的时间。
更新:是的,您可以使用Monitor课程代替lock()
。您可以使用Monitor.TryEnter()方法检查对象是否已被锁定(即:如果您想返回错误而不是等待)。
更多详情:
来自http://msdn.microsoft.com/en-us/library/aa664735(VS.71).aspx:
表格的锁定声明
lock (x) ...
其中x是引用类型的表达式,恰好等同于
System.Threading.Monitor.Enter(x);
try {
...
}
finally {
System.Threading.Monitor.Exit(x);
}
来自http://msdn.microsoft.com/en-us/library/de0542zz.aspx:
使用Enter获取作为参数传递的对象的Monitor。如果另一个线程在对象上执行了Enter,但尚未执行相应的Exit,则当前线程将阻塞,直到另一个线程释放该对象。
因此,只是按设计,代码知道阻止而不是跳过。如果您想使用Monitor.TryEnter()方法,可以跳过。
答案 1 :(得分:2)
我不知道它是如何在.net中实现的,但我想你想要实现一个锁定对象,它在被服务时由一个请求“拥有”,并且一次不能被赋予多个请求。在Java中,我可能会在某个全局对象上进行同步。
但要小心,注意通常的并发问题...对于一个天真的实现,一个请求检查锁并找到它可用,然后休眠,第二个请求检查锁并获取它,然后第一个请求醒来,认为锁是免费的,坏事发生)。另外,请确保处理请求处理崩溃而使锁定到位的情况。
由于使用基于Web的非并发系统的使用模式(当然在Java servlets世界中)是一种不好的做法,我建议你在服务已经存在的情况下抛出一个错误使用而不是阻止因为可能难以判断阻塞的影响。
答案 2 :(得分:2)
我理解一次只处理一个请求的要求,但我认为一次只允许一个请求就是答案。
部分答案建议阻止请求。虽然这会在小范围内起作用,但这会导致诸如超时和扩展能力等问题,导致更多服务器出现。
另一种方法是,您在每个请求进入时为其提供服务并将其放在队列上以供稍后处理。此队列可以一次处理一个任务(或者取决于服务器的繁忙程度)。
原始请求者可以通过几种方式通知完成。一种方法是轮询以查看原始请求是否已完成,或者是否仍在队列中进行处理,可能使用生成的令牌(例如GUID)。
答案 3 :(得分:0)
我不知道你为什么要这样做,但无论如何,这可能是一个有效的场景。试着看看Linux的APT包管理器如何获得锁定:
为了防止包管理器的多个实例产生,要使包管理器正常工作,它需要锁定锁文件并将其写入其中。
同样,您可以在虚拟主机的根目录中创建文件。连接客户端时,锁定该文件,即在其中写入内容。完成后,将文件设为空。在尝试锁定它之前,试着看看里面是否有东西。如果是,则将错误消息返回给客户端。