Domanda

Sia Thread.Sleep (timeout) ed esecuzione resetEvent.Wait (timeout) motivo di pausa di almeno millisecondi timeout, quindi c'è una differenza tra loro? So che Thread.Sleep causa il filo di abbandonare il resto della sua porzione di tempo, provocare così un sonno che dura molto più a lungo richiesto. Il metodo di Wait (timeout) di un oggetto ManualResetEvent hanno lo stesso problema?

Modifica : Mi rendo conto che il punto principale di un ManualResetEvent deve essere segnalato da un altro thread - adesso sto interessa solo il caso di metodo Wait di un evento con un timeout specificato, e altri chiamanti impostazione dell'evento. Voglio sapere se è più affidabile di risvegliare in tempo di quanto Thread.Sleep

È stato utile?

Soluzione

Thread.Sleep(timeout) provoca un'attesa senza condizioni prima dell'esecuzione viene ripreso. resetEvent.WaitOne(timeout) fa sì che il filo di aspettare fino a quando (1) l'evento viene attivato, o è raggiunta (2) il timeout.

Il punto di usare eventi è quello di innescare loro da un altro thread, in modo da poter controllare direttamente quando il thread si sveglia. Se non avete bisogno di questo, non si dovrebbe essere utilizzando gli oggetti evento.

EDIT: Timing-saggio, sono entrambi ugualmente affidabili. Tuttavia, i suoi commenti su "risveglio in tempo" mi preoccupa. Perché è necessario il codice a svegliarsi in tempo? Sleep e WaitOne non sono realmente progettati con precisione in mente.

Solo se timeout è inferiore a 50ms o giù di lì ed è necessario l'affidabilità , si dovrebbe guardare in metodi alternativi di tempistica. sguardi questo articolo come una panoramica piuttosto buona.

Altri suggerimenti

La differenza principale tra Thread.Sleep e href="http://msdn.microsoft.com/en-us/library/system.threading.waithandle.waitone.aspx" rel="noreferrer"> ManualResetEvent.WaitOne è che si può segnalare a un thread in attesa su una ManualResetEvent utilizzando il Set metodo, causando il filo di svegliarsi prima del timeout.

Se non segnalano poi ci si aspetta che si comportino in un modo molto simile.

Da .NET Reflector posso vedere che il metodo ManualResetEvent.WaitOne alla fine si traduce in una chiamata a un metodo extern con la seguente firma:

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

considerando che Thread.Sleep chiama questo metodo extern:

void SleepInternal(int millisecondsTimeout);

Purtroppo non ho il codice sorgente per questi metodi, quindi posso solo immaginare. Mi immagino che in entrambe le chiamate provocano il filo sempre in programma fuori mentre si è in attesa del tempo per scadere, senza né particolarmente più accurato rispetto agli altri.

Per ritardi e periodics ho trovato Monitor.Wait una scelta buona ..

object timelock = new object();

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

Questo dà un ottimo risultato .... ~ 1ms jitter o meglio a seconda delle specifiche applicazioni.

Come forse già sapete Thread.Sleep (X) è inaffidabile e non può essere cancellato .... lo evito come la peste.

La funzione Sleep () non ha funzionato in questo modo per un lungo periodo di tempo. La sua precisione è determinata dal periodo di timer multimediale, qualcosa che si può cambiare da P / Invocazione timeBeginPeriod (). Purtroppo, sulla mia macchina ho un qualche tipo di programma che stabilisce questo periodo per un millisecondo, rendendo posti letto verso il basso preciso per un millesimo di secondo. Ecco il codice per provare per lei:

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

Uscita sulla mia macchina:

Il sonno: 999, Wait: 1003

con una variabilità di circa 5 millisecondi.

Come altri hanno detto, la differenza viene WaitOne potrebbe tornare prima del tempo di sonno, se segnalata. Il sonno è garantito per attendere il tempo di sonno.

Thread.Sleep nelle chiamate riflettore:

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

ManualResetEvent.Wait nelle chiamate riflettore:

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

Non so se c'è una differenza tra i due, ma vedrò se riesco a trovare qualcosa.

Il sonno continua per il periodo di tempo specificato. L'attesa evento può terminare prima se l'evento viene segnalato. Questo è lo scopo di eventi:. Per consentire un thread di raccontare un altro per svegliare

In una discussione che ci si dice:

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

In un altro che ci si dice:

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

Senza la chiamata al Set in altro thread, il primo thread farebbe in modo efficace il sonno per 10 secondi.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top