SemaphorefullException - 逻辑错误引发?

发布于 2024-11-05 00:39:03 字数 2012 浏览 1 评论 0原文

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

如果有人可以看一下下面的示例代码,我将非常感激让我知道我哪里出了问题,因为在这个阶段我想我开始发疯了..

请注意,“真正的”代码不仅有一个线程循环,而且它非常接近

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;
    }

}

I have a multithreaded application, of which one of the classes uses a semaphore to control reading & writing. This seems to work fine most of the time, however I'm getting some inexplicable semaphorefull exceptions thrown, indicating that I'm trying to release when I shouldn't be. The problem is I've been over my code & can't seem to find a flaw in the logic which would cause this to happen.

I would be really grateful if someone could take a look at the sample code below & let me know where I'm going wrong as at this stage I think I'm beginning to go mad..

Please note that the "real" code doesn't just have a loop of threads but its pretty close

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;
    }

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

梦在夏天 2024-11-12 00:39:04

Semaphore 通过 WaitHandle - 当您的 WorkerClass Dispose 本身是 Dispose-d 时,您需要将其设置为 Dispose

public class WorkClass : IDisposable

using (WorkClass workClass = new WorkClass())

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

Semaphore is IDisposable through WaitHandle - you need to make your WorkerClass Dispose it when it's Dispose-d of itself.

public class WorkClass : IDisposable

using (WorkClass workClass = new WorkClass())

Perhaps you are hitting some system limit under load due to unDisposed Semaphore instances? This may not be THE problem but it is A problem, regardless of any redesign you do to make pool static, or other singleton mechanism.

优雅的叶子 2024-11-12 00:39:04

事实上,您在工作类之外传递信号量(包装在 Token 实例中)可能表明您正在其他地方使用它,除了 BeginRead>结束阅读

如果信号量仅在 WorkClass 内部使用,我强烈建议将其从 Token 中完全删除 - 将其设为私有静态字段(如 吉姆指出)并向世界其他地方隐藏它。

The fact that you are passing the semaphore outside of your worker class (wrapped in a Token instance) may indicate that you are using it somewhere else, other that BeginRead and EndRead.

If semaphore is used only inside the WorkClass, I would strongly recommend removing it from the Token completely - make it a private static field (as Jim pointed out) and hide it from the rest of the world.

拥抱没勇气 2024-11-12 00:39:03

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

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

One problem you're going to run into here is that you're creating a new semaphore for each instance of the WorkClass. So if you have three WorkClass instances, there will be three separate semaphores. I think you want your semaphore to be static, so that all instances share the one semaphore. You call it _pool, so I assume there's a limited number of shared resources that you want all instances to access.

I don't see how the code you presented in your question can throw a SemaphoreFullException. Are you certain that the code you posted is functionally equivalent to the code that you're having trouble with? If you compile and run the code that you posted, do you get that exception?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文