14

c# 中的单次旋转需要多长时间?我想知道的是有一个 ManualResetEventSlim 有一个 spinCount 参数,我想知道每次旋转的时间以毫秒为单位或它是如何工作的?我知道旋转对于短等待比内核等待更有效。所以我只是想看看我应该为通常需要 2-10 秒的工作设置这个值。

4

2 回答 2

32

spinCount构造函数中的参数与执行旋转等待所花费的毫秒数之间没有关联。

下面是它的工作原理。MRES 使用此spinCount参数来完成自己的等待程序,独立于Thread.SpinWait.

  • Thread.Yield前 10 次迭代在调用和之间交替Thread.SpinWait。呼叫以Thread.SpinWait旋转开始,Environment.ProcessorCount * 4然后在每次连续呼叫时大约翻倍。
  • 此后每次迭代都可以被 20 次调用整除Thread.Sleep(1)
  • 否则那些能被 5 整除的电话Thread.Sleep(0)
  • 否则Thread.Yield被调用。
  • 100次CancellationToken后每 10 次迭代检查一次。

如您所见,在 MRES 的自定义旋转程序中进行了相当复杂的歌舞。并且算法可能会因版本而异。真的没有办法预测每次旋转会持续多长时间。

如果您的典型等待时间是 2-10 秒,那么您的代码几乎肯定会通过Monitor.WaitMonitor.Pulse协调进行内核级等待,因为spinCount无论如何参数都限制为 2047。

另外,2-10 秒是很长的时间。你真的想转那么久吗?

于 2012-04-24T20:44:09.073 回答
13

旋转计数应该很小。默认值为 10(如果在单处理器上运行,则为 1)。如果您使用允许您指定旋转计数的构造函数,则允许的最大值为 2047。如果事件没有很快发出信号,则 ManualResetEventSlim 使用常规事件句柄等待。正如@HenkHolterman 所提到的,所涉及的时间远比几秒钟小得多。我们说的是周期,而不是秒甚至毫秒。

http://msdn.microsoft.com/en-us/library/5hbefs30.aspx

在 .NET Framework 版本 4 中,您可以使用 System.Threading.ManualResetEventSlim 类在预期等待时间非常短且事件不跨越进程边界时获得更好的性能。ManualResetEventSlim 在等待事件发出信号时使用短时间忙碌旋转。当等待时间很短时,旋转可能比使用等待句柄等待要便宜得多。但是,如果事件在特定时间段内未发出信号,ManualResetEventSlim 将求助于常规事件句柄等待。

http://msdn.microsoft.com/en-us/library/ee722114.aspx

在多核计算机上,当资源预计不会被长时间持有时,等待线程在用户模式下自旋几十或几百个周期,然后重试获取资源会更有效率. 如果资源在旋转后可用,那么您已经节省了数千个周期。如果资源仍然不可用,那么您只花费了几个周期,仍然可以进入基于内核的等待。

编辑:要直接回答您的问题,单次旋转的时间长度无法明确回答,因为它取决于运行它的硬件。 http://msdn.microsoft.com/en-us/library/system.threading.thread.spinwait(v=vs.95).aspx

SpinWait 实质上将处理器置于一个非常紧凑的循环中,循环计数由迭代参数指定。因此,等待的持续时间取决于处理器的速度。

于 2012-04-24T20:34:07.450 回答