由逻辑错误引发的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;
}
}
您将在这里遇到的一个问题是,您正在为WorkClass
的每个实例创建一个新的信号量。所以如果你有三个WorkClass
实例,就会有三个独立的信号量。我认为您希望您的信号量为static
,以便所有实例共享一个信号量。您将其称为_pool
,因此我假设您希望所有实例访问的共享资源数量有限。
我不明白你在问题中提出的代码如何抛出SemaphoreFullException
。你确定你发布的代码与你遇到问题的代码在功能上是等同的吗?如果你编译并运行你发布的代码,你会得到那个异常吗?
Semaphore
是IDisposable
通过waithhandle -你需要让你的WorkerClass
Dispose
当它是Dispose
-d本身。
public class WorkClass : IDisposable
using (WorkClass workClass = new WorkClass())
也许由于未处置的信号量实例,您在负载下达到了一些系统限制?这可能不是的问题,但它是一个问题,无论您做任何重新设计使pool
静态,或其他单例机制。
在worker类之外传递信号量(包装在Token
实例中)的事实可能表明您正在其他地方使用它,而不是BeginRead
和EndRead
。
如果信号量仅在WorkClass
中使用,我强烈建议将其从Token
中完全删除-使其成为私有静态字段(如Jim指出的)并将其隐藏起来。