AsyncSemaphore 不是 .NET 原生类型,而是社区基于 SemaphoreSlim 封装的语法糖;SemaphoreSlim 本身已原生支持异步等待(WaitAsync)和取消令牌,直接使用更简可控。
没有这个类型 —— 它是社区封装的“语法糖”,不是 .NET 原生类;而是官方提供的、支持异步等待的轻量信号量。
为什么搜不到
的官方文档?
因为
并不存在于
或任何 .NET 标准库中。它是开发者(比如在 NuGet 上的
或某些开源项目)基于
封装的一层薄包装,目的通常是:
把
+
模式固化成
友好结构
自动处理
(比如用
或
)
隐藏
传递细节
它不解决新问题,只是让常见用法更安全、不易漏
。
本身已原生支持异步:别绕路封装
.NET Framework 4.5+ 和所有 .NET Core / .NET 5+ 都自带
,无需额外引入“AsyncSemaphore”类。直接用它就是最简、最可控的方式:
注意要点:
支持
,能响应取消请求(
不支持)
必须配对
,否则计数泄漏 → 后续所有
都会永久挂起
不要在
块外释放 ——
是底线,
不适用(它没实现
)
什么时候才该考虑封装一个“AsyncSemaphore”?
仅当你的项目反复出现以下模式,且团队多人容易写错时:
C知道
CSDN推出的一款AI技术问答工具
下载
每次都要手写
+
经常忘记传
,导致无法取消等待
需要统一记录等待超时、统计并发峰值等可观测性逻辑
此时可自己写一个极简封装(20 行内),例如:
}
但请记住:这仍是建立在
之上的便利层,不是替代品。
真正容易被忽略的是:无论用原生
还是自封的
,都必须确保
在 *每一次*
成功后被执行 —— 缺一次,整个信号量就卡死。这不是异常,也不会报错,只会让后续所有线程/任务无声地 hang 住。
AsyncSemaphoreSemaphoreSlimAsyncSemaphoreAsyncSemaphoreSystem.ThreadingMicrosoft.VisualStudio.ThreadingSemaphoreSlimWaitAsync()usingawait usingRelease()IDisposableIAsyncDisposableCancellationTokenReleaseSemaphoreSlimSemaphoreSlim.WaitAsync()var semaphore = new SemaphoreSlim(initialCount: 3, maxCount: 3);
await semaphore.WaitAsync(cancellationToken);
try
{
// 执行受保护的异步操作
await SomeIoOperationAsync();
}
finally
{
semaphore.Release();
}
WaitAsync()CancellationTokenSemaphoreRelease()WaitAsync()catchtry/finallyusingIAsyncDisposabletry/finallyRelease()cancellationTokenpublic sealed class AsyncSemaphore : IAsyncDisposable
{
private readonly SemaphoreSlim _semaphore;
public AsyncSemaphore(int initialCount) => _semaphore = new SemaphoreSlim(initialCount);
public async ValueTask EnterAsync(CancellationToken ct = default)
{
await _semaphore.WaitAsync(ct);
return new Releaser(_semaphore);
}
private struct Releaser : IDisposable
{
private readonly SemaphoreSlim _s;
public Releaser(SemaphoreSlim s) => _s = s;
public void Dispose() => _s.Release();
}
public async ValueTask DisposeAsync() => await Task.CompletedTask;
SemaphoreSlimSemaphoreSlimAsyncSemaphoreRelease()WaitAsync()