信号量异常 - 将指定的计数添加到信号量会导致它超过其最大计数

Semaphore exception - Adding the specified count to the semaphore would cause it to exceed its maximum count

我遇到这个 SemaphoreFullException 已经有一段时间了。

总结.. 我使用 ASP.NET v4.0 框架应用程序池(集成)在 IIS 7.5 上托管了一个应用程序。 我正在使用 windows 身份验证通过域 (isinrole) 对我的用户进行身份验证。

我看过关于此主题的所有其他线程,其中建议设置 Pooling = False。 我不想那样做,因为性能优势,我想继续使用池化。

我正在使用 Entity Framework 6 查询数据库,我不是 "disposing" 用户代码中任何地方的 dbcontext。 看起来问题出在 DbConnectionPool 代码中。

错误在任何给定时刻随机发生。应用程序是否正在使用并不重要。有时,由于这个问题 - 我必须重新启动 IIS,因为新用户停止获得身份验证。

到目前为止我尝试过的:

注意:在我的应用程序中,我主要使用 linq-to-EF 对象来查询数据库。

Exception: System.Threading.SemaphoreFullException

Message: Adding the specified count to the semaphore would cause it to exceed its maximum count.

StackTrace:    at System.Threading.Semaphore.Release(Int32 releaseCount)
   at System.Data.ProviderBase.DbConnectionPool.CleanupCallback(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.TimerQueueTimer.CallCallback()
   at System.Threading.TimerQueueTimer.Fire()
   at System.Threading.TimerQueue.FireNextTimers()

在这方面的任何帮助将不胜感激。

我认为这可能是解决问题的方法:http://www.davepaquette.com/archive/2013/03/27/managing-entity-framework-dbcontext-lifetime-in-asp-net-mvc.aspx - 如您所见,在 DbContext 的生命周期结束时处理 DbContext 非常重要。

请记住,数据库连接最终会出现在非托管数据库处理代码中,所以问题是除非垃圾回收处理它在主内存中保持休眠的上下文,从而也阻止来自连接池的连接。所以迟早,在合适的条件下,你会清空连接池并得到你的异常。

我遇到了同样的问题,因为我在关闭连接之前做了 .Dispose(); 这就是我解决它的方法:

我有两个 .Dispose(); 的实例 - 一个在 SqlDataAdapter 中,另一个在一个 SqlCommand 中,然后关闭连接并出现错误。 刚刚从我的 SqlCommand 和我的 SqlDataAdapter 中删除了 .Dispose();,没有更多的错误!我希望这会有所帮助。

就我而言,问题是我在调试时停止了应用程序。该应用程序正在进行大量异步调用。

所以我重置了我的 IIS 服务器:iisreset 通过命令提示符或 PowerShell,它成功了。

EDIT: Look at the @aaroncatlin comment for IIS Express

我最近遇到了类似的 SemaphoreSlim 问题。有问题的代码如下,在 semaphoreSlime.Release() 中引发了相同的异常。这里的原因是 WaitAsync 由于令牌取消而失败,因此 Release() 将导致超出允许的最大计数。因此,一个解决方案是在调用 Release() 之前添加一些防御代码,例如检查 WaitAsync 期间是否发生异常,检查允许的帐户是否超过允许的数量。

try
{
   await semaphoreSlim.WaitAsync(cancellationToken);
   // do some work
}
catch (OperationCanceledException)
{
   // exception handling
}
finally
{
   semaphoreSlim.Release();
}