简体   繁体   English

为什么ManualResetEventSlim.Wait似乎没有在整个等待时间内阻塞?

[英]Why does ManualResetEventSlim.Wait appear not to block for the full wait time?

So I am using System.Threading.ManualResetEventSlim in my code and I happened to notice that sometimes when I call Wait(TimeSpan) the time spent waiting is significantly less than the time specified. 因此,我在代码中使用System.Threading.ManualResetEventSlim ,并且偶然发现有时我调用Wait(TimeSpan)花费的时间明显少于指定的时间。

Here is a unit test that demonstrates my situation 这是一个演示我的情况的单元测试

using System;
using System.Diagnostics;
using NUnit.Framework;

namespace DB
{
    [TestFixture]
    public class ManualResetEventSlimTests
    {
        [Test]
        [Repeat(100)]
        public void TestThatWait_ShouldBlockForAtLeastAsLongAsTheWaitTimeout_IfNotSignalled()
        {
            TimeSpan waitTime = TimeSpan.FromMilliseconds(250);
            using (var waiter = new System.Threading.ManualResetEventSlim(false))
            {
                var stopwatch = System.Diagnostics.Stopwatch.StartNew();
                waiter.Wait(waitTime);
                Assert.That(stopwatch.Elapsed, Is.GreaterThanOrEqualTo(waitTime));
            }
        }
    }
}

This test will pass most of the time but when repeated 100 times there is always at least 1 failure because the time measured by the stopwatch is less than the specified wait TimeSpan. 该测试将在大多数时间通过,但当重复100次时,由于秒表测得的时间小于指定的等待时间,因此总是至少有1次失败。 A typical failure is 典型的故障是

Expected: greater than or equal to 00:00:00.2500000 But was: 00:00:00.2497514 预期:大于或等于00:00:00.2500000,但是:: 00:00:00.2497514

My first thought was that the stopwatch was not accurate enough but that appears not to be the case; 我首先想到的是秒表不够准确,但事实并非如此。 the Stopwatch.Frequency = 3507511, which means that it should be accurate to something like 285ns per tick ie much, much less than the discrepancy of 0.25ms (assuming that it can accurately count ticks). Stopwatch.Frequency = 3507511,这意味着它应该精确到大约每秒钟285ns,即远小于0.25ms的差异(假设它可以准确地计算滴答)。

The fact that it waits a few fractions of a ms less than I expected does not have any impact on my particular program but I was curious and my Google-foo did not uncover anything relevant. 它等待的时间比我预期的少了几分之一毫秒,这一事实对我的特定程序没有任何影响,但是我很好奇,我的Google-foo没有发现任何相关内容。 So I put it to the SO community to see if someone has a reasonable explanation. 因此,我将其放在SO社区中,以查看是否有人有合理的解释。

ManualResetEventSlim ultimately uses Environment.TickCount (see http://referencesource.microsoft.com/#mscorlib/system/threading/ManualResetEventSlim.cs,8a17ba6e95765ed8 and http://referencesource.microsoft.com/#mscorlib/system/threading/SpinWait.cs,9212529427afb371 ) . ManualResetEventSlim最终使用Environment.TickCount (请参阅http://referencesource.microsoft.com/#mscorlib/system/threading/ManualResetEventSlim.cs,8a17ba6e95765ed8http://referencesource.microsoft.com/#mscorlib/system/threading/SpinWait。 cs,9212529427afb371 )。 The docs state: 文档状态:

Note that, because it is derived from the system timer, the resolution of the TickCount property is limited to the resolution of the system timer, which is typically in the range of 10 to 16 milliseconds 请注意,由于它是从系统计时器派生的,因此TickCount属性的分辨率仅限于系统计时器的分辨率,该范围通常在10到16毫秒之间

As such, Stopwatch is likely being more accurate / precise than ManualResetEventSlim . 因此, Stopwatch可能比ManualResetEventSlim更准确。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM