2025-10-11 18:25:59 +08:00

53 lines
2.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}
}