c# - 不执行方法释放锁
问题描述
我正在使用的系统由托管各种 WCF 服务的 Windows 服务组成。多个客户端可以与同一个服务通信,但一次只有一个客户端可以与一个服务通信。
因此,我使用“lock()”来防止多个客户端发生冲突。如果 Client1 向服务发出第一个请求,然后 Client2 在前者仍在执行时发出另一个请求,则“锁定”会暂停第二个请求,直到第一个请求完成。
到目前为止,一切都很好。现在的问题是我必须处理事件(我不认为简单的回调会在这里解决问题)。
换句话说,当第一个请求正在运行时,可能会发生一些 Client2 需要知道的事情。
发生这种情况时,Client2 将收到该事件并最终应该一起停止使用该服务。
这里的问题是我们的第二个请求已经在储物柜的队列中。
那么我将如何阻止第二个请求运行。可以取消吗?
也许这只是添加一个脏标志的问题,但我希望有更好的方法来做到这一点。
这是带有脏标志“canRun”的服务端的样子:
lock (_locker)
{
if (canRun)
return SomeMethod();
else
return null;
}
解决方案
如果你可以切换到async
/await
和类似 a 的东西SemaphoreSlim
,那么:CancellationToken
就是你要找的东西;aCancellationTokenSource
可以随时标记为已取消,并且代码可以相应地响应 - 大多数框架/库代码已经正确处理取消,例如:在异步信号量获取期间。
如果您需要坚持同步世界,那么您最好的选择可能是更改为Monitor
可以重新检查每次超时的循环模式,例如:
bool lockTaken = false;
try
{
do
{
if (!canRun) throw new OperationCanceledException();
Monitor.TryEnter(_locker, someTimeout, ref lockTaken);
}
while (!lockTaken);
// now we have the conch
SomeMethod();
}
finally
{
if (lockTaken) Monitor.Exit(_locker);
}
请注意,如果canRun
是一个字段,您将希望确保它被volatile
适当地访问或以其他方式访问,以避免被缓存在寄存器或类似物中。
推荐阅读
- r - 确定日期戳和参考日期之间的差异
- python - 使用 key.get_pressed() 的键事件问题
- c# - Blazored Modals 似乎没有打开
- java - 通过java bean访问自定义控件compositeData值
- html - 如何根据列的大小缩小行宽 - Bootstrap
- junit - kafka的集成测试用例
- vb.net - sendkeys.Send - 运行多次后突然失败 - 错误 - 访问被拒绝 - RDP .net
- performance - 如何提高嵌套循环的速度/寻找更高效的代码
- pandas - 选择其值正常的列
- kibana - Kibana Query 获取发生次数