有没有一种方法可以在多个SemaphoreSlim上异步等待,比如WaitHandle.WetAny()



我正在将一个应用程序转换为异步,它在一些地方使用了Semaphores。

将这些Semaphores转换为SemaphoreSlims,我能够在大多数地方使用WaitAsync异步等待。

但是,在一些地方,应用程序使用WaitHandle.WaitAny((等待多个信号量

是否有一种以异步方式实现此功能的有效方法?

基本上,我如何异步转换以下通用代码:

Semaphore sem1 = new Semaphore(1,1);
SemaPhore sem2 = new Semaphore(1,1);
WaitHandle[] sems = new WaitHande[2];
sems[0] = sem1;
sems[1] = sem2;
int index = WaitHandle.WaitAny(sems);
if(index = 0){ do some operation }
else if(index == 1) { do some other operation }

我想避免使用Task.Run和相同的阻塞调用,因为这会使线程池紧张,因为线程在等待时会被阻塞,比如:

await Task.Run(() => WaitHandle.WaitAny(sems));

此外,我并不局限于使用SemaphoreSlim,我会考虑任何类似的构造。但是,我确实需要Semaphores提供的节流功能。

如果可以使用SemaphoreSlim,则答案可以使用WhenAny;您只需要确保取消或释放不想要的信号量:

SemaphoreSlim sem1 = new(1,1);
SemaphoreSlim sem2 = new(1,1);
CancellationTokenSource cts = new();
Action done;
var sem1Task = sem1.WaitAsync(cts.Token);
var sem2Task = sem2.WaitAsync(cts.Token);
var completedTask = await Task.WhenAny(sem1Task, sem2Task);
cts.Cancel();
if (completedTask == sem1Task)
{
done = sem1.Release;
await ReleaseIfNecessaryAsync(sem2Task, sem2);
}
else
{
done = sem2.Release;
await ReleaseIfNecessaryAsync(sem1Task, sem1);
}
if (completedTask == sem1Task) { do some operation }
else if (completedTask == sem2Task) { do some other operation }
done();
static async Task ReleaseIfNecessaryAsync(Task waitTask, SemaphoreSlim sem)
{
try
{
await waitTask;
sem.Release();
}
catch (OperationCanceledException) { }
}

最新更新