【问题标题】:Semaphore timeout after exception异常后信号量超时
【发布时间】:2014-03-12 20:29:19
【问题描述】:

我在管理来自多个模块的资源时遇到了一些麻烦,这些模块一次只能安全访问一次。

所以我尝试了一个像这样命名的Semaphore

var semaphore = new Semaphore(1, 1, "_UGLY_SEMAPHORE_NAME_");

        try
        {
            var signaled = semaphore.WaitOne(120000); // 2 minutes

            if (!signaled)
            {
                return;
            }

            // Access the resource...
        }
        finally
        {
            semaphore.Release();
        }

在我使用的另一个模块中

var signaled = semaphore.WaitOne(0); 

因为只有在无事可做时才能访问资源。 它会在 6 秒后稳定返回,所以我相信 2 分钟应该足够了。

所以问题是:

如果第一个代码块发生异常,之后的 Semaphore.WaitOne() 总是遇到超时。我做错了什么。

【问题讨论】:

  • 异常发生在哪里?是在“// Access the resource...”中,还是在谈论奇怪的边缘情况,在不寻常的地方出现类似线程中止异常?
  • 是的。它在该代码之外处理并调用 finally。我对“发布增量和 WaitOne 减量”部分感到有些困惑。
  • 然后查看Semaphore的文档,或者在Google上查找;这是一个定义合理的 CS 概念。
  • 你是对的,有很多文档。但如果我能在那里找到答案,我真的不会问这个问题。
  • 如果你想要互斥,那么你应该使用Mutex而不是Semaphore

标签: c# multithreading try-catch semaphore


【解决方案1】:

处理过程中发生的异常不会导致任何其他线程在信号量上等待超时。 finally 块的语义意味着,如果异常导致 try 块结束,它就会执行,从而释放信号量。

【讨论】:

  • 那么,为什么我在异常后第二次进入第一个代码块时会超时?我很确定这与我使用 WaitOne 和 Release 所做的事情有关,但我无法弄清楚。
  • @MareInfinitus 那么要么你没有显示你正在使用的实际代码,要么你没有正确观察结果。
  • 问题中的代码是我正在使用的代码,我正在观察这种行为。所以你认为它应该如上所示工作?
  • 它的工作原理如图所示。如果那是您拥有的代码,那么您认为正在发生的事情实际上并没有发生。例如,您可能没有在等待您认为的信号量,或者即使代码抛出异常,您也可能不会离开 try 块。
  • 我在 isSignaled 和 finally 块中有断点。问题是关于我观察到的。我尝试做一个更小的例子来重现我看到的行为。
【解决方案2】:

我怀疑问题是你调用sempahore.Release()不管线程是否进入信号量。如果代码路径进入信号量,您应该只调用Release,否则计数器可能会因为您在未获取信号量时释放信号量而被抛出。

var semaphore = new Semaphore(1, 1, "_UGLY_SEMAPHORE_NAME_");

var signaled = semaphore.WaitOne(120000); // 2 minutes

if (!signaled)
{
    return;
}
try
{
    // Access the resource...
}
finally
{
    semaphore.Release();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-07
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    相关资源
    最近更新 更多