【发布时间】:2016-06-30 07:05:00
【问题描述】:
我有一个用于单元测试的MockHttpListener 回调。我给它加了一个锁,如下所示:
public void HandleRequest(HttpListenerContext context)
{
try
{
lock (m_guard)
{
do something short;
}
do the actual handling (longer)
}
catch (HttpListenerException e)
{
...
}
catch (Exception e)
{
...
}
...
}
我遇到了一个测试失败的问题,因为我们有“花费太长时间”的标准(我在添加锁之前的测试中没有遇到这个问题。)
我尝试了很多方法来确定问题,唯一解决问题的方法是将锁放在 try 块之外:
public void HandleRequest(HttpListenerContext context)
{
lock (m_guard)
{
do something short;
}
try
{
do the actual handling (longer)
}
catch (HttpListenerException e)
{
...
}
catch (Exception e)
{
...
}
...
}
在相对于 try 块的锁定位置影响测试完成的持续时间方面,行为变化是一致的。
有人知道原因吗?
【问题讨论】:
-
考虑阅读此stackoverflow.com/questions/5997360/…。它会让你知道它为什么会发生。
-
@hazevich 这并没有告诉你为什么它更慢,但它确实告诉你你不应该允许未处理的异常从
lock中逃脱块。您需要在lock块内使用try/finally来清理内容。但这对这里的 OP 没有帮助,我认为。 -
我阅读了链接中的线程,但它讨论了在 try 块中使用锁的正确性。我只对性能影响感兴趣。考虑到所有考虑的锁定块可以认为仅由:m_some_member++组成;没有别的,所以它本身就很安全。
-
如果您只是在读取然后有条件地递增,您可以尝试使用 ReaderWriterLockSlim (msdn.microsoft.com/en-us/library/…) 而不是锁。在某些情况下,联锁 (msdn.microsoft.com/en-us/library/…) 也可能是一个不错的选择。
-
是太长还是挂起?如果是后者,则表明锁定逻辑本身存在问题(对代码的任何更改都可能改变时序)。实际上,这也可能是前者的原因,尽管可能性较小。在其他个地方会发生什么情况?
标签: c#