由逻辑错误引发的SemaphorefullException

本文关键字:SemaphorefullException 错误 | 更新日期: 2023-09-27 17:54:43

我有一个多线程应用程序,其中一个类使用信号量来控制读取&写作。这似乎在大多数时候都很好,但是我得到了一些无法解释的信号异常抛出,表明我试图在不应该释放的时候释放。问题是我已经检查过我的代码了。我似乎找不出导致这种情况发生的逻辑缺陷。

如果有人能看看下面的示例代码,我将非常感激。让我知道我哪里错了,因为在这个阶段,我觉得我开始发疯了。

请注意,"真正的"代码不只是一个线程循环,而是非常接近

class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 100; i++)
        {
            Thread t = new Thread(() => ThreadA());
            t.Start();
        }            
    }
    /// <summary>
    /// Run the methods in the worker class
    /// </summary>
    private static void ThreadA()
    {
        Token token = null;
        WorkClass workClass = new WorkClass();
        try
        {
            workClass.BeginRead(out token, "A");                
        }
        finally
        {
            workClass.EndRead(token);
        }
    }       
}
/// <summary>
///  this class does the actual work
/// </summary>
public class WorkClass
{
    private Semaphore _pool = new Semaphore(2, 2);
    public void BeginRead(out Token token, string s)
    {
        Semaphore sem = null;
        try
        {
            // wait for the main semaphore to signal
            _pool.WaitOne();
            // set local semaphore equal to main
            sem = _pool;
            //simulate work
            Thread.Sleep(100);
        }
        finally
        {
            //return the token with the semaphore
            token = new Token(sem, s);
        }
    }
    public void EndRead(Token token)
    {
        try
        {
            // do some more work
        }
        finally
        {
            // release the semaphore if not null
            if (null != token.signal)
            {
                token.signal.Release();
            }
        }
    }    
}

public class Token
{
   internal readonly Semaphore signal;
   internal readonly string s;
    internal Token(Semaphore _signal, string _s)
    {
        this.s = _s;
        this.signal = _signal;
    }
}

由逻辑错误引发的SemaphorefullException

您将在这里遇到的一个问题是,您正在为WorkClass的每个实例创建一个新的信号量。所以如果你有三个WorkClass实例,就会有三个独立的信号量。我认为您希望您的信号量为static,以便所有实例共享一个信号量。您将其称为_pool,因此我假设您希望所有实例访问的共享资源数量有限。

我不明白你在问题中提出的代码如何抛出SemaphoreFullException。你确定你发布的代码与你遇到问题的代码在功能上是等同的吗?如果你编译并运行你发布的代码,你会得到那个异常吗?

SemaphoreIDisposable通过waithhandle -你需要让你的WorkerClass Dispose当它是Dispose -d本身。

public class WorkClass : IDisposable
using (WorkClass workClass = new WorkClass())

也许由于未处置的信号量实例,您在负载下达到了一些系统限制?这可能不是问题,但它是一个问题,无论您做任何重新设计使pool静态,或其他单例机制。

在worker类之外传递信号量(包装在Token实例中)的事实可能表明您正在其他地方使用它,而不是BeginReadEndRead

如果信号量仅在WorkClass中使用,我强烈建议将其从Token中完全删除-使其成为私有静态字段(如Jim指出的)并将其隐藏起来。

相关文章:
  • 没有找到相关文章