Quelle est la différence entre Thread.Sleep (délai d'attente) et ManualResetEvent.Wait (délai d'attente)?

StackOverflow https://stackoverflow.com/questions/2999093

Question

Les deux Thread.Sleep (délai d'attente) et resetEvent.Wait (délai d'attente) l'exécution de la cause à une pause pendant au moins quelques millisecondes timeout, donc est-il une différence entre eux? Je sais que Thread.Sleep provoque le fil d'abandonner le reste de sa tranche de temps, ce qui entraîne donc peut-être dans un sommeil qui dure beaucoup plus longtemps que demandé. Est-ce que la méthode d'attente (délai d'attente) d'un objet ManualResetEvent ont le même problème?

Modifier : Je suis conscient que doit être signalé par un autre thread principal point d'un ManualResetEvent - Je suis en ce moment ne concerne que le cas de la méthode d'attente d'un événement avec une durée d'expiration, et pas d'autres appelants réglage de l'événement. Je veux savoir si elle est plus fiable pour réveiller le temps que Thread.Sleep

Était-ce utile?

La solution

Thread.Sleep(timeout) provoque une attente sans conditions avant l'exécution reprend. resetEvent.WaitOne(timeout) amène le fil à attendre jusqu'à ce que soit (1) l'événement est déclenché, ou (2) le délai d'expiration est atteinte.

Le point d'utiliser des événements est de les déclencher d'un autre thread, de sorte que vous pouvez contrôler directement quand le fil se réveille. Si vous n'avez pas besoin, vous ne devriez pas utiliser les objets d'événement.

EDIT: TIMING sages, ils sont tous les deux aussi fiables. Cependant, vos commentaires sur « l'éveil à temps » me préoccupe. Pourquoi avez-vous besoin de votre code pour se réveiller à l'heure? Sleep et WaitOne ne sont pas vraiment conçus avec une précision à l'esprit.

Seulement si timeout est inférieure à 50 ms environ et vous avez besoin de la fiabilité , vous devriez regarder dans d'autres méthodes de synchronisation. Les regards de cet article comme une assez bonne vue d'ensemble.

Autres conseils

La fonction Sleep () n'a pas fonctionné de cette façon depuis longtemps. Sa précision est déterminée par la période de minuterie multimédia, quelque chose que vous pouvez changer par P / Invoquer timeBeginPeriod (). Malheureusement, sur ma machine, j'ai une sorte de programme qui définit cette période à une milliseconde, ce qui dort en bas précis à un millième de seconde. Voici un code pour essayer par vous-même:

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

Sortie sur ma machine:

Sommeil: 999, Attendez: 1003

avec une variabilité d'environ 5 millisecondes.

Comme d'autres l'ont mentionné, la différence est WaitOne pourrait revenir avant l'heure de sommeil si signalé. Le sommeil est garanti d'attendre le temps de sommeil.

Thread.Sleep dans les appels réflecteur:

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

ManualResetEvent.Wait dans les appels réflecteur:

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

Je ne sais pas s'il y a une différence entre les deux, mais je vais voir si je peux trouver quelque chose.

Le sommeil se poursuit pendant la durée spécifiée. L'attente de l'événement peut se terminer plus tôt si l'événement est signalé. Tel est le but des événements. Pour permettre à un fil de dire une autre de se réveiller

Dans un fil que vous souhaitez dire:

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

Dans une autre vous dirais:

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

Sans l'appel à Set dans l'autre fil, le premier fil serait effectivement le sommeil pendant 10 secondes.

scroll top