Frage

Beide Gewinde.Sleep(timeout) und resetEvent.Wait(timeout) die Ausführung pause für mindestens timeout Millisekunden, so gibt es einen Unterschied zwischen Ihnen?Ich weiß, dass Thread.Schlaf bewirkt, dass der thread zu geben, den Rest seiner Zeitscheibe, so womöglich einen erholsamen Schlaf, dauert viel länger als gefragt.Hat die Wartezeit(timeout) - Methode eines ManualResetEvent-Objekt das gleiche problem haben?

Bearbeiten:Ich bin mir bewusst, dass ein ManualResetEvent, die Hauptsache ist, signalisiert werden, aus einem anderen thread - jetzt bin ich nur noch beschäftigt mit dem Fall eines Ereignisses Warten Methode mit einem timeout angegeben ist, und die keine anderen Anrufer Einstellung der Veranstaltung.Ich möchte wissen, ob es mehr zuverlässig zu Erwachen, auf-Zeit als Thread.Schlafen

War es hilfreich?

Lösung

Thread.Sleep(timeout) verursacht eine bedingungslose Wartezeit, bevor die Ausführung wieder aufgenommen wird. resetEvent.WaitOne(timeout) Bewirkt, dass der Faden wartet, bis entweder (1) das Ereignis ausgelöst wird, oder (2) das Timeout erreicht ist.

Es geht darum, Ereignisse zu verwenden, um sie von einem anderen Thread auszulösen, sodass Sie direkt steuern können, wenn der Faden aufwacht. Wenn Sie dies nicht benötigen, sollten Sie keine Ereignisobjekte verwenden.

Bearbeiten: Timing In Bezug auf sind beide gleichermaßen zuverlässig. Ihr Kommentar zum "pünktlichen Erwachen" macht mich jedoch Sorgen. Warum brauchen Sie Ihren Code, um pünktlich aufzuwachen? Sleep und WaitOne Sie sind nicht wirklich mit Präzision konzipiert.

Nur wenn timeout ist unter 50 ms oder so und Sie benötigen die Zuverlässigkeit, Sie sollten sich mit alternativen Timing -Methoden befassen. Dieser Artikel Sieht nach einem ziemlich guten Überblick aus.

Andere Tipps

Der Hauptunterschied zwischen Thread.Sleep und ManualResetEvent.WaitOne ist, dass Sie einem Faden signalisieren können, der auf einen Handbuch wartet Satz Methode, wodurch der Thread früher als die Zeitüberschreitung aufwacht.

Wenn Sie nicht signalisieren, würde ich erwarten, dass sie sich auf sehr ähnliche Weise verhalten.

Aus .NET -Reflektor kann ich sehen, dass die Methode ManualResetEvent.WaitOne führt schließlich zu einem Aufruf einer externen Methode mit der folgenden Signatur:

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

Wohingegen Thread.Sleep Ruft diese externe Methode auf:

void SleepInternal(int millisecondsTimeout);

Leider habe ich nicht den Quellcode für diese Methoden, also kann ich nur raten. Ich würde mir vorstellen, dass in beiden Anrufen der Thread geplant wird, während er darauf wartet, dass die Zeit abgelaufen ist, wobei keiner besonders genauer als der andere ist.

Für Verzögerungen und Perioden habe ich Monitor gefunden. Warte eine gute Wahl.

object timelock = new object();

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

Dies ergibt ein hervorragendes Ergebnis ... ~ 1 ms Jitter oder besser, abhängig von Anwendungsspezifikationen.

Wie Sie vielleicht bereits wissen, ist Thread.sleep (x) unzuverlässig und kann nicht abgesagt werden ... Ich vermeide es wie die Pest.

Die Sleep () - Funktion nicht auf diese Weise gearbeitet haben für eine lange Zeit.Die Genauigkeit ist bestimmt durch die multimedia-timer Zeit, etwas, was Sie ändern können, indem Sie P/Aufrufen timeBeginPeriod().Leider, auf meinem Rechner habe ich eine Art von Programm, die diese Zeit zu einer Millisekunde, wodurch schläft genaue herab zu einer Millisekunde.Hier finden Sie den code, um zu versuchen, für sich selbst:

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

Die Ausgabe auf meiner Maschine:

Schlafen:999, Warten:1003

mit einer Variabilität von etwa 5 Millisekunden.

Wie andere erwähnt haben, könnte der Unterschied darin bestehen, dass Waitone vor der Schlafzeit zurückkehren könnte, wenn sie signalisiert werden. Der Schlaf wartet garantiert auf die Schlafzeit.

Thread.Seep in Reflektoraufrufen:

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

ManualResetEvent.wait bei Reflektoranrufen:

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

Ich bin mir nicht sicher, ob es einen Unterschied zwischen den beiden gibt, aber ich werde sehen, ob ich etwas finden kann.

Der Schlaf setzt sich für die angegebene Zeit fort. Das Ereigniswart kann früher enden, wenn das Ereignis signalisiert wird. Dies ist der Zweck von Ereignissen: Er lassen einen Thread einen anderen aufwachen.

In einem Thread würden Sie sagen:

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

In einem anderen würden Sie sagen:

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

Ohne den Anruf zu Set Im anderen Faden würde der erste Faden 10 Sekunden lang effektiv schlafen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top