WaitHandle.WaitAny和Semaphore类

Tho*_*rin 6 .net c# multithreading waithandle

编辑:我甚至想提出这个问题暂时疯狂,但当时有意义(见下面的编辑2).

对于.NET 3.5项目,我有两种类型的资源(R1R2),我需要检查它的可用性.每种资源类型可以随时(例如)有10个实例.

当其中一种资源可用时,我的工作线程需要唤醒(存在可变数量的线程).在早期的实现中,只有一种资源类型,我使用Semaphore来检查可用性.

现在我需要等待两个单独的信号量(S1S2)来跟踪资源的可用性.

WaitHandle[] waitHandles = new WaitHandle[] { s1, s2 };
int signalledHandle = WaitHandle.WaitAny(waitHandles);

switch (signalledHandle)
{
    case 0:
        // Do stuff
        s1.Release();
    case 1:
        // Do stuff
        s2.Release();
}
Run Code Online (Sandbox Code Playgroud)

然而,这有一个问题.从MSDN文档WaitAny:

如果在调用期间发出多个对象的信号,则返回值是具有所有信号通知对象的索引值最小的信号通知对象的数组索引.

这表明我可能会在打电话后将我的信号量计数减少1 WaitAny.因为signalledHandle将指示s1已发出信号,我将开始使用资源R1,并在完成后释放它.但是,由于我不知道S2是否已发出信号,因此此资源的可用性计数现在可能已关闭.如果发生这种情况10次,我的信号量将永久"空",资源R2将不再使用.

处理这个问题的最佳方法是什么?我是否应该从使用两个信号量切换到简单计数器,并在任何一个计数器更改时发出AutoResetEvent信号?我错过了一些更优雅的方法吗?

编辑1:
根据Ravadre的说法,之后只有一个信号量会被改变WaitAny.略微修改他的例子似乎证实了这一点,但有没有人可以指出我指出这个的一些官方文件?

编辑2:
我在回家的路上想着这个.只有这样,我才意识到,WaitAny任何用途都必须如此.这个问题不仅限于信号量,而是几乎任何类型的同步对象,WaitAny几乎没用.

Mar*_*uła 5

如果我理解你的问题,我认为你的解决方案是完全正常的,而你只是在解释msdn引用.在调用时,WaitHandle.WaitAny()您将获得最低的索引,但是您将仅锁定一个waitHandle(在本例中为信号量),请检查以下示例代码:


Semaphore s1 = new Semaphore(1, 2);
Semaphore s2 = new Semaphore(1, 2);

WaitHandle[] handles = new WaitHandle[] { s1, s2 };

int x = WaitHandle.WaitAny(handles);

int prevS1 = s1.Release();
int prevS2 = s2.Release();
Run Code Online (Sandbox Code Playgroud)

在这种情况下,prevS1将等于0,因为信号量s1"等待",所以它的计数器已经减少到0,而prevS2将等于1,因为它的状态没有改变,因为它的实例化(Release()方法之前返回计数器)释放,所以返回1意味着"它是1,现在它是2").

您可能想要查看的另一个资源:http://www.albahari.com/threading/part2.aspx#_Wait_Handles.虽然它不是"官方"来源,但我认为没有理由认为它不可靠.