using System; using System.Threading; using System.Threading.Tasks; namespace XiaoZhiSharp.Kernels { /*使用示例: private static AsyncSemaphore s_asyncSemaphore = new AsyncSemaphore(); Task.Run(async () => { using (await s_asyncSemaphore.WaitAsync()) { //await ...... } }); */ /// /// C# 在await中使用Lock出现cannot await in the body of a lock statement解决方法 /// 如果试图在 lock 块中使用 async 关键字时使用 lock 关键字, /// 会得到这个编译错误:cannot await in the body of a lock statement。 /// 原因是在async 完成之后,该方法可能会在一个不同的线程中运行,而不是在async 关键字之前。 /// lock 关键字需要同一个线程中获取锁和释放锁。 /// 如何解决这个问题? /// 不能为此使用 Monitor,因为 Monitor 需要从它获取锁的同一线程中释放锁。lock 关键字基于 Monitor。 /// 虽然 Mutex 对象可以用于不同进程之间的同步,但它有相同的问题:它为线程授予了一个锁。 /// 从不同的线程中释放锁是不可能的。 /// 相反,可以使用 Semaphore 或 SemaphoreSlim 类。 /// Semaphore 可以从不同的线程中释放信号量。 /// https://blog.csdn.net/weixin_67336587/article/details/125219994 /// public sealed class AsyncSemaphore { private class SemaphoreReleaser : IDisposable { private SemaphoreSlim _semaphore; public SemaphoreReleaser(SemaphoreSlim semaphore) => _semaphore = semaphore; public void Dispose() => _semaphore.Release(); } private SemaphoreSlim _semaphore; public AsyncSemaphore() => _semaphore = new SemaphoreSlim(1); public async Task WaitAsync() { await _semaphore.WaitAsync(); return new SemaphoreReleaser(_semaphore) as IDisposable; } } }