【问题标题】:Why does ManualResetEventSlim.Wait appear not to block for the full wait time?为什么 ManualResetEventSlim.Wait 似乎没有阻塞整个等待时间?
【发布时间】:2017-07-06 09:13:36
【问题描述】:

所以我在我的代码中使用了System.Threading.ManualResetEventSlim,我碰巧注意到有时当我调用Wait(TimeSpan) 时,等待的时间明显少于指定的时间。

这是一个演示我的情况的单元测试

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));
            }
        }
    }
}

这个测试大部分时间都会通过,但是当重复 100 次时,总是至少有 1 次失败,因为秒表测量的时间小于指定的等待时间跨度。一个典型的失败是

预期:大于或等于 00:00:00.2500000 但是是:00:00:00.2497514

我的第一个想法是秒表不够准确,但事实并非如此; Stopwatch.Frequency = 3507511,这意味着它应该精确到每滴答声 285ns,即远小于 0.25ms 的差异(假设它可以准确计算滴答声)。

它等待的时间比我预期的少几分之一毫秒,这对我的特定程序没有任何影响,但我很好奇,我的 Google-foo 没有发现任何相关信息。所以我把它放在SO社区,看看是否有人有合理的解释。

【问题讨论】:

    标签: c# manualresetevent


    【解决方案1】:

    ManualResetEventSlim 最终使用Environment.TickCount(参见http://referencesource.microsoft.com/#mscorlib/system/threading/ManualResetEventSlim.cs,8a17ba6e95765ed8http://referencesource.microsoft.com/#mscorlib/system/threading/SpinWait.cs,9212529427afb371)。文档状态:

    注意,因为是系统定时器派生的,所以分辨率 TickCount 属性的限制为系统的分辨率 定时器,通常在 10 到 16 毫秒的范围内

    因此,Stopwatch 可能比 ManualResetEventSlim 更准确/精确。

    【讨论】:

      猜你喜欢
      • 2023-03-09
      • 2017-11-11
      • 2023-03-11
      • 1970-01-01
      • 2015-11-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-23
      相关资源
      最近更新 更多