thread.sleep(超时)和resetevent.wait(超时)导致执行至少暂停 timeout 毫秒,它们之间有区别吗?我知道该线程会导致线程放弃其剩余时间切片,因此可能导致睡眠持续时间比要求的时间更长。 ManualResetevent对象的等待(超时)方法是否存在相同的问题?

编辑: :我知道,手动Resetevent的要点是要从另一个线程发出信号 - 现在,我只关心事件的等待方法,其中指定了超时,没有其他呼叫者设置事件。我想知道是否比线程更可靠地唤醒。

有帮助吗?

解决方案

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

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

编辑:定时,它们都同样可靠。但是,您对“按时觉醒”的评论让我担心。为什么您需要代码准时醒来? SleepWaitOne 并不是真正的精确设计。

除非 timeout 低于50ms左右,您需要可靠性, ,您应该研究定时的替代方法。 本文 看起来是一个很好的概述。

其他提示

主要区别 Thread.SleepManualResetEvent.WaitOne 是您可以使用使用该线的线程发出信号 方法,导致线程比超时更早醒来。

如果您不信号,那么我希望他们的行为非常相似。

从.NET反射器我可以看到该方法 ManualResetEvent.WaitOne 最终导致呼吁具有以下签名的外部方法:

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

然而 Thread.Sleep 称此外部方法:

void SleepInternal(int millisecondsTimeout);

不幸的是,我没有这些方法的源代码,所以我只能猜测。我想,在两个呼叫中,这都会导致线程在等待时间到期时被安排出来,而没有比另一个特别精确。

对于延迟和期间,我找到了监视器。等待一个不错的选择。

object timelock = new object();

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

这给出了极好的结果.... 〜1ms抖动或更好的取决于应用程序的细节。

您可能已经知道螺纹。Sleep(x)是不可靠的,无法取消。...我像瘟疫一样避免了它。

Sleep()函数已经很长时间了。它的精度取决于多媒体计时器周期,您可以通过p/indoking 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);
}

在我的机器上输出:

睡眠:999,等待:1003

可变性约为5毫秒。

正如其他人提到的那样,差异是怀特对如果发出信号之前的睡眠时间可以返回。睡眠可以保证等待睡眠时间。

thread.sleep在反射器调用中:

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

ManualResetevent。在反射器呼叫中的等待:

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

不确定两者之间是否有区别,但是我会看看是否可以找到东西。

睡眠继续在指定的时间内。如果事件发出信号,活动等待可以更早结束。这是事件的目的:允许一个线程告诉另一个线程醒来。

在一个线程中,您会说:

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

在另一个您中,您会说:

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

没有电话 Set 在另一个线程中,第一个线程将有效睡10秒钟。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top