Bagaimana caranya agar program C # saya tidur selama 50 msec?

272

Bagaimana caranya agar program C # saya tidur selama 50 milidetik?

Ini mungkin pertanyaan yang mudah, tetapi saya mengalami kegagalan otak sementara!

TK.
sumber
1
Ditandai ulang ke VB.NET karena jawabannya juga berfungsi di sana.
DrFloyd5
Tidak ada DrFloyd5,; tidak berfungsi di VB.NET, kan?
Zanoni
16
Jika saya berada di tim VB.Net, saya akan menambahkan; sebagai karakter komentar ke versi bahasa berikutnya ...
Joel Coehoorn
4
Saya pikir pemrogram VB cukup cerdas untuk menemukan yang setara ..
BlueRaja - Danny Pflughoeft
baik, hanya untuk memastikan, sekarang mereka tidak perlu.
PsychoData

Jawaban:

330
System.Threading.Thread.Sleep(50);

Ingat juga, bahwa melakukan ini di utas GUI utama akan memblokir GUI Anda dari pembaruan (akan terasa "lamban")

Hapus saja ;untuk membuatnya bekerja untuk VB.net juga.

Isak Savo
sumber
Setelah memanggil sleep dalam suatu metode, apakah program akan terus dijalankan di latar belakang (tanpa membuat utas baru)? Juga, jika saya sebut sleep di utas baru, akankah utas utama melanjutkan kerjanya?
Jay Nirgudkar
@JayNirgudkar utas yang menyebut Sleep akan dihentikan. Utas lainnya tidak terpengaruh.
Isak Savo
Ini tidak dijamin akurat.
Akumaburn
150

Pada dasarnya ada 3 pilihan untuk menunggu (hampir) bahasa pemrograman:

  1. Longgar menunggu
    • Menjalankan blok ulir untuk waktu tertentu (= tidak mengkonsumsi daya pemrosesan)
    • Tidak ada pemrosesan yang dimungkinkan pada utas yang diblokir / menunggu
    • Tidak terlalu tepat
  2. Tight waiting (disebut juga loop ketat)
    • Prosesor sangat sibuk untuk seluruh interval menunggu (pada kenyataannya, biasanya menghabiskan 100% dari waktu pemrosesan satu inti)
    • Beberapa tindakan dapat dilakukan sambil menunggu
    • Sangat tepat
  3. Kombinasi 2 sebelumnya
    • Biasanya menggabungkan efisiensi pemrosesan 1. dan ketepatan + kemampuan untuk melakukan sesuatu 2.

untuk 1. - Longgar menunggu di C #:

Thread.Sleep(numberOfMilliseconds);

Namun, Windows Thread Scheduler menyebabkan akurasi Sleep()sekitar 15ms (jadi Sleep dapat dengan mudah menunggu hingga 20ms, bahkan jika dijadwalkan hanya menunggu 1ms).

untuk 2. - Ketat menunggu di C # adalah:

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

Kita juga bisa menggunakan DateTime.Nowatau cara lain pengukuran waktu, tetapi Stopwatchjauh lebih cepat (dan ini akan benar-benar terlihat dalam loop ketat).

untuk 3. - Kombinasi:

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
}

Kode ini secara teratur memblokir utas selama 1 ms (atau sedikit lebih, tergantung pada penjadwalan utas OS), sehingga prosesor tidak sibuk untuk waktu pemblokiran itu dan kode tidak menghabiskan 100% daya prosesor. Pemrosesan lainnya masih dapat dilakukan di antara pemblokiran (seperti: memperbarui UI, menangani acara atau melakukan hal-hal interaksi / komunikasi).

Marcel Toth
sumber
1
Timer juga mungkin menarik
JonnyRaa
55

Anda tidak dapat menentukan waktu tidur yang pasti di Windows. Anda memerlukan OS waktu nyata untuk itu. Yang terbaik yang dapat Anda lakukan adalah menentukan waktu tidur minimum . Kemudian terserah penjadwal untuk membangunkan utas Anda setelah itu. Dan tidak pernah memanggil .Sleep()utas GUI.

Joel Coehoorn
sumber
44

Karena sekarang Anda memiliki fitur async / menunggu, cara terbaik untuk tidur selama 50 ms adalah dengan menggunakan Task.Delay:

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

Atau jika Anda menargetkan .NET 4 (dengan Async CTP 3 untuk VS2010 atau Microsoft.Bcl.Async), Anda harus menggunakan:

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

Dengan cara ini Anda tidak akan memblokir utas UI.

Toni Petrina
sumber
dapatkah Anda respons. siram selama penundaan ini, jika dalam satu lingkaran?
Teoman shipahi
Tidak Anda tidak bisa. Saya percaya ada FlushAsyncversi.
Toni Petrina
6
Alternatif yang tidak memerlukan asyncdeklarasi adalah meneleponTask.Delay(50).Wait();
stuartd
31

Gunakan kode ini

using System.Threading;
// ...
Thread.Sleep(50);
Alexander Prokofyev
sumber
14
Thread.Sleep(50);

Utas tidak akan dijadwalkan untuk dieksekusi oleh sistem operasi untuk jumlah waktu yang ditentukan. Metode ini mengubah status utas untuk menyertakan WaitSleepJoin.

Metode ini tidak melakukan pemompaan COM dan SendMessage standar. Jika Anda perlu tidur di utas yang memiliki STAThreadAttribute, tetapi Anda ingin melakukan pemompaan COM dan SendMessage standar, pertimbangkan untuk menggunakan salah satu kelebihan dari metode Bergabung yang menentukan interval waktu habis.

Thread.Join
SelvirK
sumber
5

Untuk dibaca:

using System.Threading;
Thread.Sleep(TimeSpan.FromMilliseconds(50));
Kolonel Panic
sumber
0

Dimulai dengan .NET Framework 4.5, Anda dapat menggunakan:

using System.Threading.Tasks;

Task.Delay(50).Wait();   // wait 50ms
timmebee
sumber
-1

Terbaik dari kedua dunia:

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