53 lines
2.0 KiB
C#
Raw Normal View History

2025-10-11 18:25:59 +08:00
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 ......
}
});
*/
/// <summary>
/// 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
/// </summary>
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<IDisposable> WaitAsync()
{
await _semaphore.WaitAsync();
return new SemaphoreReleaser(_semaphore) as IDisposable;
}
}
}