代码之家  ›  专栏  ›  技术社区  ›  Erik Forbes

Thread.Sleep(超时)和ManualResetEvent.Wait(超时)之间有什么区别?

  •  9
  • Erik Forbes  · 技术社区  · 15 年前

    Thread.Sleep(超时)和resetEvent.Wait(超时)都会导致执行至少暂停一段时间 timeout

    编辑 :我知道ManualResetEvent的主要点是从另一个线程发出信号-现在我只关心指定超时的事件等待方法的情况,没有其他调用程序设置该事件。我想知道准时醒来是否比睡觉更可靠

    6 回复  |  直到 15 年前
        1
  •  26
  •   zildjohn01    15 年前

    Thread.Sleep(timeout) 导致在执行恢复之前进行无条件等待。 resetEvent.WaitOne(timeout) 使线程等待,直到(1)触发事件或(2)达到超时。

    使用事件的目的是从另一个线程触发它们,因此您可以直接控制线程何时唤醒。如果不需要,就不应该使用事件对象。

    Sleep WaitOne 在设计上并没有考虑到精确性。

    timeout 低于50ms左右,需要可靠性 ,您应该研究其他计时方法。 This article 看起来是一个很好的概述。

        2
  •  10
  •   Mark Byers    15 年前

    Thread.Sleep ManualResetEvent.WaitOne 您可以使用 Set 方法,使线程在超时之前唤醒。

    手动重置事件.WaitOne 最终导致调用具有以下签名的extern方法:

    int WaitOneNative(SafeWaitHandle waitHandle,
                      uint millisecondsTimeout,
                      bool hasThreadAffinity,
                      bool exitContext);
    

    鉴于 线程。睡眠 调用此外部方法:

    void SleepInternal(int millisecondsTimeout);
    

        3
  •  7
  •   Rusty    15 年前

    对于延迟和周期,我找到了监视器。等等,一个好的选择。。

    object timelock = new object();
    
    lock (timelock) { Monitor.Wait(timelock, TimeSpan.FromMilliseconds(X.XX)); }
    

    你可能已经知道了,睡眠(X)是不可靠的,不能被取消……我像躲避瘟疫一样逃避它。

        4
  •  4
  •   Hans Passant    15 年前

    Sleep()函数已经很久没有这样工作了。它的准确性由多媒体计时器周期决定,您可以通过P/调用timeBeginPeriod()来更改它。不幸的是,在我的机器上,我有一个程序,把这个周期设置为一毫秒,使睡眠精确到一毫秒。下面是一些代码供您自己尝试:

    using System;
    using System.Diagnostics;
    using System.Threading;
    using System.Runtime.InteropServices;
    
    class Program {
        static void Main(string[] args) {
            //timeBeginPeriod(1);
            var sw1 = Stopwatch.StartNew();
            for (int ix = 0; ix < 100; ++ix) Thread.Sleep(10);
            sw1.Stop();
            var sw2 = Stopwatch.StartNew();
            var mre = new ManualResetEvent(false);
            for (int ix = 0; ix < 100; ++ix) mre.WaitOne(10);
            sw1.Stop();
            Console.WriteLine("Sleep: {0}, Wait: {1}", sw1.ElapsedMilliseconds, sw2.ElapsedMilliseconds);
            Console.ReadLine();
            //timeEndPeriod(1);
        }
        [DllImport("winmm.dll")]
        private static extern int timeBeginPeriod(int period);
        [DllImport("winmm.dll")]
        private static extern int timeEndPeriod(int period);
    }
    

    我的机器上的输出:

    变化约为5毫秒。

        5
  •  2
  •   SwDevMan81    15 年前

    正如其他人提到的,不同的是,如果有信号的话,一个人可以在睡眠时间之前返回。睡眠是保证等待的睡眠时间。

    线程。睡眠反射调用:

    [MethodImpl(MethodImplOptions.InternalCall)]
    private static extern void SleepInternal(int millisecondsTimeout);
    

    private static extern int WaitOneNative(SafeWaitHandle waitHandle, uint millisecondsTimeout, bool hasThreadAffinity, bool exitContext);
    

    我不确定这两者是否有区别,但我会看看能不能找到什么。

        6
  •  1
  •   Daniel Earwicker    15 年前

    睡眠将持续指定的时间。如果用信号通知事件,则事件等待可以更快结束。这就是事件的目的:允许一个线程告诉另一个线程唤醒。

        mre.WaitOne(10000); // ten seconds
        Console.WriteLine("Woke up!");
    

    另一方面,你会说:

        mre.Set(); // this causes `WaitOne` to return in the first thread
    

    Set 在另一个线程中,第一个线程将有效睡眠10秒。