在ManualResetEventSlim中旋转多长时间

时间:2012-04-24 19:39:11

标签: c# multithreading c#-4.0

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

2 个答案:

答案 0 :(得分:29)

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

以下是它的工作原理。 MRES使用此spinCount参数来独立于Thread.SpinWait进行自己的等待例程。

  • 前10次迭代在调用Thread.YieldThread.SpinWait之间交替。对Thread.SpinWait的调用以Environment.ProcessorCount * 4的旋转开始,然后在每次连续调用时大约翻倍。
  • 此后每次迭代可以被20个调用Thread.Sleep(1)整除。
  • 否则可被5整除的人请致电Thread.Sleep(0)
  • 否则调用Thread.Yield
  • 在100之后每10次检查CancellationToken

所以你可以看到在MRES的定制旋转程序中有一个相当复杂的歌舞。并且算法可以从版本更改为版本。实际上没有办法预测每次旋转会持续多长时间。

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

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

答案 1 :(得分:12)

旋转计数意味着很小。默认值为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本质上将处理器置于一个非常紧密的循环中   迭代参数指定的循环计数。持续时间   因此等待取决于处理器的速度。