it-swarm.it

Come posso far dormire il mio programma C # per 50 msec?

Come faccio a far dormire il mio programma C # per 50 millisecondi?

Questa potrebbe sembrare una domanda facile, ma sto avendo un momento temporaneo di insuccesso cerebrale!

259
TK.
System.Threading.Thread.Sleep(50);

Ricorda però che fare questo nel thread della GUI principale bloccherà la tua GUI dall'aggiornamento (sembrerà "pigra")

Basta rimuovere ; per farlo funzionare anche per VB.net.

309
Isak Savo

Ci sono fondamentalmente 3 scelte per aspettare (quasi) qualsiasi linguaggio di programmazione:

  1. attesa allentata
    • Esecuzione di blocchi di thread per un tempo determinato (= non consuma potenza di elaborazione)
    • Nessuna elaborazione è possibile sul thread bloccato/in attesa
    • Non così preciso
  2. Stretta attesa (chiamata anche ciclo chiuso)
    • il processore è MOLTO impegnato per l'intero intervallo di attesa (infatti, di solito consuma il 100% del tempo di elaborazione di un core)
    • Alcune azioni possono essere eseguite durante l'attesa
    • Molto preciso
  3. Combinazione dei precedenti 2
    • Solitamente combina l'efficienza di elaborazione di 1. e la precisione + capacità di fare qualcosa di 2.

per 1. - In attesa in C #:

Thread.Sleep(numberOfMilliseconds);

Tuttavia, l'utilità di pianificazione dei thread di Windows fa sì che l'accuratezza di Sleep() sia di circa 15 ms (quindi Sleep può facilmente attendere 20 ms, anche se pianificato per attendere solo 1 ms).

per 2. - Stretta attesa in C # è:

Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
    //some other processing to do possible
    if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
    {
        break;
    }
}

Potremmo anche usare DateTime.Now o altri mezzi di misurazione del tempo, ma Stopwatch è molto più veloce (e questo diventerebbe davvero visibile in un loop ristretto).

per 3. - Combinazione:

Stopwatch stopwatch = Stopwatch.StartNew();
while (true)
{
    //some other processing to do STILL POSSIBLE
    if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
    {
        break;
    }
    Thread.Sleep(1); //so processor can rest for a while
}

Questo codice blocca regolarmente il thread per 1 ms (o leggermente di più, in base alla pianificazione dei thread del sistema operativo), quindi il processore non è occupato per il tempo di blocco e il codice non consuma il 100% della potenza del processore. È comunque possibile eseguire altre elaborazioni tra un blocco e l'altro (ad esempio: aggiornamento dell'interfaccia utente, gestione di eventi o attività di interazione/comunicazione).

146
Thetam

Non è possibile specificare un esatto tempo di sospensione in Windows. Hai bisogno di un sistema operativo in tempo reale per questo. Il meglio che puoi fare è specificare un minimo tempo di sonno. Quindi spetta al programmatore di riattivare il thread dopo. E never chiama .Sleep() sul thread della GUI.

54
Joel Coehoorn

Poiché ora disponi di funzionalità asincrone/attese, il modo migliore per dormire per 50 ms è utilizzare Task.Delay:

async void foo()
{
    // something
    await Task.Delay(50);
}

O se si utilizza .NET 4 (con Async CTP 3 per VS2010 o Microsoft.Bcl.Async), è necessario utilizzare:

async void foo()
{
    // something
    await TaskEx.Delay(50);
}

In questo modo non bloccherai il thread dell'interfaccia utente.

44
Toni Petrina

Usa questo codice

using System.Threading;
// ...
Thread.Sleep(50);
31
Thread.Sleep(50);

Il thread non verrà pianificato per l'esecuzione dal sistema operativo per la quantità di tempo specificato. Questo metodo cambia lo stato del thread per includere WaitSleepJoin.

Questo metodo non esegue il pompaggio COM e SendMessage standard. Se è necessario dormire su un thread che dispone di STAThreadAttribute, ma si desidera eseguire il pompaggio standard COM e SendMessage, considerare l'utilizzo di uno degli overload del metodo Join che specifica un intervallo di timeout.

Thread.Join
14
SelvirK
Thread.Sleep
10
Roger Lipscombe

Per leggibilità:

using System.Threading;
Thread.Sleep(TimeSpan.FromMilliseconds(50));
3
Colonel Panic

Il meglio di entrambi i mondi:

using System.Runtime.InteropServices;

    [DllImport("winmm.dll", EntryPoint = "timeBeginPeriod", SetLastError = true)]
    private static extern uint TimeBeginPeriod(uint uMilliseconds);

    [DllImport("winmm.dll", EntryPoint = "timeEndPeriod", SetLastError = true)]
    private static extern uint TimeEndPeriod(uint uMilliseconds);
    /**
     * Extremely accurate sleep is needed here to maintain performance so system resolution time is increased
     */
    private void accurateSleep(int milliseconds)
    {
        //Increase timer resolution from 20 miliseconds to 1 milisecond
        TimeBeginPeriod(1);
        Stopwatch stopwatch = new Stopwatch();//Makes use of QueryPerformanceCounter WIN32 API
        stopwatch.Start();

        while (stopwatch.ElapsedMilliseconds < milliseconds)
        {
            //So we don't burn cpu cycles
            if ((milliseconds - stopwatch.ElapsedMilliseconds) > 20)
            {
                Thread.Sleep(5);
            }
            else
            {
                Thread.Sleep(1);
            }
        }

        stopwatch.Stop();
        //Set it back to normal.
        TimeEndPeriod(1);
    }
0
Akumaburn