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