53 lines
2.0 KiB
C#
53 lines
2.0 KiB
C#
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;
|
||
}
|
||
}
|
||
}
|