WaitHandle.WaitAny和Semaphore类编辑:问这个问题我一时发疯了,但当时是有道理的(见下面的编辑2)。对于.NET3.5项目,我有两种类型的资源(R1和R2),我需要检查其可用性。任何时候每种资源类型可以有(例如)10个实例。当其中一个资源可用时,我的工作线程需要唤醒(线程数量可变)。在早期的实现中,只有一种资源类型,我使用信号量来检查可用性。现在我需要等待两个单独的信号量(S1和S2)来跟踪资源可用性。WaitHandle[]waitHandles=newWaitHandle[]{s1,s2};intsignalledHandle=WaitHandle。WaitAny(waitHandles);switch(signalledHandle){case0://做事s1。发布();案例1://做事s2.Release();然而,这有一个问题。来自WaitAny的MSDN文档:如果在调用期间有多个对象发出信号,则返回值是信号对象的数组索引,其中所有信号对象具有最小的索引值。这表明我可能会在调用WaitAny后将我的信号量计数减1。由于signalledHandle将指示s1已发出信号,因此我将开始使用资源R1并在完成后释放它。但是,由于我不知道S2是否已发出信号,因此此资源的可用性计数现在可能已关闭。如果这种情况发生10次,我的信号量将永久“空”,资源R2将不再使用。处理这个问题的最佳方法是什么?我是否应该从使用两个信号量切换到一个简单的计数器并在任一计数器更改时发出AutoResetEvent信号?我错过了一些更优雅的方法吗?编辑1:根据Ravadre的说法,在WaitAny之后,只会更改一个信号量。稍微修改一下他的例子似乎证实了这一点,但谁能给我指出一些指出这一点的官方文件?编辑2:我在回家的路上一直在想这个。这时我才意识到WaitAny一定有用。这个问题并不局限于信号量,而是几乎任何一种同步对象,使得WaitAny几乎无用。如果我理解你的问题,我认为你的解决方案非常好,你只是在解释msdn参考。当调用WaitHandle.WaitAny()时,您将获得最低的索引,但您只会锁定一个waitHandle(在本例中为信号量),请查看示例代码:Semaphores1=newSemaphore(1,2);信号量s2=新信号量(1,2);WaitHandle[]handles=newWaitHandle[]{s1,s2};intx=WaitHandle.WaitAny(句柄);intprevS1=s1.Release();intprevS2=s2.Release();在这种情况下,prevS1将等于0,因为信号量s1正在“等待”,因此它的计数器已递减为0,而prevS2将等于1,因为它的状态自实例化以来没有改变(Release())方法在释放之前返回计数器,因此返回1意味着“它是1,现在是2”。您可能想要查看的另一个资源:http://www.albahari.com/threading/part2.aspx#_Wait_Handles。虽然它是不是“官方”来源,我认为没有理由认为它不可靠。出于您的目的,在调用WaitHandle.WaitAny()方法时,结果并不重要。重要的是发出WaitHandle信号,因此您可以进行另一次尝试需要获取锁/同步。voidMain(){varsemaphoreOne=newSemaphoreSlim(0,1);varsemaphoreTwo=newSemaphoreSlim(0,1);ReleaseSemaphoreAfterWhile(semaphoreOne);boolfirstAccepted;boolsecondAccepted=false;while((firstAccepted=semaphoreOne.Wait(0))==false&&(secondAccepted=semaphoreTwo.Wait(0))==false){varwaitHandles=new[]{semaphoreOne.AvailableWaitHandle,semaphoreTwo.AvailableWaitHandle};WaitHandle.WaitAny(waitHandles);Console.WriteLine("SemaphoreOneBeforeLock="+semaphoreOne.CurrentCount);Console.WriteLine("SemaphoreTwoBeforeLock="+semaphoreTwo.CurrentCount);}if(firstAccepted){Console.WriteLine("semaphore1waslocked");}elseif(secondAccepted){Console.WriteLine("semaphore2waslocked");}else{thrownewInvalidOperationException("没有发出信号量");}}随机rd=newRandom();publicvoidReleaseSemaphoreAfterWhile(SemaphoreSlimsemaphore){varsleepWork=(int)rd.Next(100,1000);线程池l.QueueUserWorkItem(t=>{Thread.Sleep(10000+sleepWork);semaphore.Release();});其他实现有空间使用相同的想法/逻辑,但以这种方式使用while循环保证只获取一个信号量,如果没有空间,它会锁定线程直到任何WaitHandle发出信号-考虑SemaphoreSlim实例。Release()方法不幸的是(如评论中所指出的)它们对于网络中的线程同步存在一些误解,但上面的代码应该可以帮助您。以上就是C#学习教程分享的全部内容:WaitHandle.WaitAny和Semaphore类。如果对你有用,需要进一步了解C#学习教程,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权请点击右侧联系管理员删除。如需转载请注明出处:
