在Semaphore的WaitOne(Int32)方法的MSDN docs中,它表示给它一个零值会导致该方法立即返回而不等待一个槽打开。 SemaphoreSlim版本的文档没有说同样的事情。 SemaphoreSlim会分享这种行为吗?
我不知道如何保证自己测试的时机。
答案 0 :(得分:8)
如果超时为0,则SemaphoreSlim.Wait
将始终尝试在返回之前获取一个插槽,它不会等待一个时间超过几个操作并且SpinOnce
。
编辑:澄清:这可能与Semaphore
的行为相同。来自Semaphore
的文档:
它测试等待句柄的状态并立即返回
但是,SemaphoreSlim
通过使用SpinOnce
,确实为您提供了在Wait方法中打开的机会。
(结束编辑)
此外,SemaphoreSlim
在尝试获取插槽之前会运行一些操作。其中一个是Monitor.Enter
,所以它可以等待那个正在等待或释放过程中的其他线程。因此,它不一定会立即返回。
据我所知,事件的顺序是:
CancellationTokenRegistration
SpinWait.SpinOnce
(如果NextSpinWillYield
为true
,则跳过此项)
(编辑:我大胆地强调,第2步执行与步骤5相同的测试,让它有机会旋转并在最终测试和退出之前使插槽可用Monitor.Enter
进入锁定(与Release和WaitAsync进入的锁相同)false
AvailableWaitHandle
下的waitHandle,如果正在使用它,可用的插槽数现在再次为0 CancellationTokenRegistration
true
(注意,使用非零超时的其他线程间歇性地释放并获取用于通过调用Monitor.Wait
来保护计数器的锁,因此您不会永远等待超时为0,仅用于很短的时间。)
所以SemaphoreSlim
似乎与Sempahore
无法共享完全相同的0超时行为,因为它确实为插槽提供了打开的机会。 (也许这就是Semaphore.WaitOne
和SemaphoreSlim.Wait
的原因 - 只需更改信号量的实例化就可以在升级旧代码时导致代码无法编译,从而让我们检查行为。)
文章Semaphore vs. SemaphoreSlim并没有强调这种行为,只是两者之间的根本区别。
旁注:
有趣的是,该引用也说明了
[SemaphoreSlim] 不支持...使用等待句柄进行同步
然而SemaphoreSlim.AvailableWaitHandle的文档却有所不同。