C# 信号量没有按预期工作,无法弄清楚原因
Posted
技术标签:
【中文标题】C# 信号量没有按预期工作,无法弄清楚原因【英文标题】:C# Semaphores not working as expected, cannot figure out why 【发布时间】:2019-12-31 05:38:18 【问题描述】:我正在用 C# 构建一个 ASP.NET (.NET Framework) 应用程序我正在对一个名为“LinuxDocker”的后端服务进行 API 调用,并且我试图限制从 ASP.NET 对其进行的 12 个并发调用的数量应用。这是我写的代码:
private static Semaphore LinuxDockerSemaphore = new Semaphore(12, 12);
public static SemaphoreWaiter WaitForLinuxDocker(int timeoutMS = -1)
return new SemaphoreWaiter(LinuxDockerSemaphore, timeoutMS);
public class SemaphoreWaiter : IDisposable
Semaphore Slim;
public SemaphoreWaiter(Semaphore slim, int timeoutMS = -1)
Slim = slim;
Slim.WaitOne(timeoutMS);
public void Dispose()
Slim.Release();
然后当我调用我的后端服务时,我会这样做:
using (ConcurrencyManager.WaitForLinuxDocker())
// Call backend service here
所以看起来这应该限制为 12 个并发调用,但是当我从具有 100 个同时调用的集成测试中对其进行测试时,它基本上一次只允许 1 个请求通过,而不是一次允许 12 个调用通过。
该服务在 Windows Server 2016 和 .NET Framework 4.7 上的 IIS 上运行。
我已多次阅读此代码,但无法弄清楚为什么它不起作用。
任何帮助将不胜感激。
【问题讨论】:
您正在通过调用WaitOne
阻塞当前线程。您可能会遇到线程池饥饿的情况,由于阻塞,根本没有足够的线程来响应调用。这可能 看起来 像信号量工作不正常。我会更改为SemaphoreSlim
并使用WaitAsync
@JohanP 感谢您的反馈。 FWIW 我实际上首先尝试了 SemaphoreSlim,当它不起作用时,我尝试了 Semaphore。两者都创建了完全相同的结果(未按预期工作)。
【参考方案1】:
可能您的后端正在由多个 w3wp.exe
工作进程提供服务。因为您的信号量是在没有名称的情况下创建的,所以它是一个“本地”信号量(每个进程本地),而不是一个“全局”信号量(系统范围):
信号量有两种类型:本地信号量和命名系统信号量。如果使用接受名称的构造函数创建 Semaphore 对象,则它与该名称的操作系统信号量相关联。命名系统信号量在整个操作系统中都是可见的,可用于同步进程的活动。您可以创建多个 Semaphore 对象来表示相同的命名系统信号量,并且可以使用 OpenExisting 方法打开现有的命名系统信号量。
本地信号量仅存在于您的进程中。它可以被进程中任何引用本地信号量对象的线程使用。每个 Semaphore 对象都是一个单独的本地信号量。
参考号:Semaphore Class
【讨论】:
谢谢,这很有帮助,会试试这个。但这实际上不会增加并行度,而不是将其减少到 1 吗?我应该将每个 Semaphore 初始化为 0 然后释放它吗?以上是关于C# 信号量没有按预期工作,无法弄清楚原因的主要内容,如果未能解决你的问题,请参考以下文章