C # programımı 50 msn boyunca uykuya nasıl alabilirim?


272

C # programımı 50 milisaniye boyunca nasıl uykuya alabilirim?

Bu kolay bir soru gibi görünebilir, ancak geçici bir beyin yetmezliği anı yaşıyorum!


1
Cevap burada da çalıştıkça VB.NET'e yeniden etiketlendi.
DrFloyd5

DrFloyd5 içermez; VB.NET üzerinde çalışmıyor, değil mi?
Zanoni

16
VB.Net ekibindeydim, eklerdim; dilin bir sonraki sürümüne yorum karakteri olarak ...
Joel Coehoorn

4
Ben VB programcılar eşdeğer anlamaya yetecek kadar parlak olduğunu düşünüyorum ..
BlueRaja - Danny Pflughoeft

Eh, sadece emin olmak için, şimdi zorunda değiller.
PsychoData

Yanıtlar:


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

Yine de, bunu ana GUI iş parçacığında yapmanın GUI'nizin güncellenmesini engelleyeceğini unutmayın ("yavaş" hissedecektir)

;VB.net için de çalışması için kaldırın .


Bir yöntemde uyku çağrıldıktan sonra, program arka planda (yeni iş parçacığı oluşturmadan) yürütülmeye devam eder mi? Ayrıca, yeni bir iş parçacığında uyku çağırırsam, ana iş parçacığı çalışmaya devam edecek mi?
Jay Nirgudkar

@JayNirgudkar, Sleep adlı iş parçacığı durdurulur. Diğer dişler etkilenmez.
Isak Savo

Bunun doğru olduğu garanti edilmez.
Akumaburn

150

Temel olarak herhangi bir programlama dilinde (neredeyse) beklemek için 3 seçenek vardır:

  1. Gevşek bekleme
    • Belirli bir süre için iş parçacığı bloklarını yürütme (= işlem gücünü tüketmez)
    • Engellenen / bekleyen iş parçacığında işlem yapılamaz
    • Çok hassas değil
  2. Sıkı bekleme (sıkı döngü de denir)
    • işlemci tüm bekleme aralığı için ÇOK meşgul (aslında, genellikle bir çekirdeğin işlem süresinin% 100'ünü tüketir)
    • Beklerken bazı işlemler yapılabilir
    • Çok hassas
  3. Önceki 2'nin kombinasyonu
    • Genellikle 1 işleme verimliliğini ve 2'lik bir şey yapma hassasiyeti + yeteneğini birleştirir.

- C # için gevşek bekleme:

Thread.Sleep(numberOfMilliseconds);

Ancak, Windows iş parçacığı zamanlayıcı Sleep() (bu nedenle, Uyku sadece 1ms beklemek üzere planlanmış olsa bile kolayca bekleyebilir).

- C # 'da sıkı bekleme:

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

Ayrıca DateTime.Nowveya diğer zaman ölçüm yöntemlerini de kullanabiliriz , ancakStopwatch çok daha hızlıdır (ve bu sıkı döngüde gerçekten görünür hale gelir).

3. - Kombinasyon:

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
}

Bu kod düzenli olarak 1 ms için iş parçacığını engeller (veya işletim sistemi iş parçacığı zamanlamasına bağlı olarak biraz daha fazla), bu nedenle işlemci bu engelleme süresi için meşgul değildir ve kod işlemci gücünün% 100'ünü tüketmez. Diğer işlemler yine de engelleme arasında gerçekleştirilebilir (örneğin: kullanıcı arayüzünün güncellenmesi, olayların işlenmesi veya etkileşim / iletişim şeylerinin yapılması).


1
Zamanlayıcı da ilgi çekici olabilir
JonnyRaa

55

Windows'da tam bir uyku zamanı belirleyemezsiniz . Bunun için gerçek zamanlı bir işletim sistemine ihtiyacınız var. Yapabileceğiniz en iyi şey minimum uyku süresini belirlemektir . Sonra bundan sonra iş parçacığını uyandırmak için zamanlayıcı kalmış. Ve asla.Sleep() GUI iş parçacığını çağırmayın .


44

Artık eşzamansız / beklemede özelliğiniz olduğundan, 50ms boyunca uyumak için en iyi yol Görev kullanmaktır.

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

Veya .NET 4'ü (VS2010 veya Microsoft.Bcl.Async için Async CTP 3 ile) hedefliyorsanız aşağıdakileri kullanmalısınız:

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

Bu şekilde UI iş parçacığını engellemezsiniz.


Eğer bir döngüdeyse, bu gecikme sırasında yıkayın?
Teoman shipahi

Hayır yapamazsın. Bir FlushAsyncversiyon olduğuna inanıyorum .
Toni Petrina

6
asyncBeyan gerektirmeyen bir alternatif Task.Delay(50).Wait();
aramaktır


14
Thread.Sleep(50);

İş parçacığı, belirtilen süre boyunca işletim sistemi tarafından yürütülmesi için zamanlanmayacaktır. Bu yöntem, iş parçacığının durumunu WaitSleepJoin içerecek şekilde değiştirir.

Bu yöntem standart COM ve SendMessage pompalama gerçekleştirmez. STAThreadAttribute içeren bir iş parçacığı üzerinde uyumak gerekiyor, ancak standart COM ve SendMessage pompalama gerçekleştirmek istiyorsanız, bir zaman aşımı aralığı belirten Join yönteminin aşırı yüklerinden birini kullanmayı düşünün.

Thread.Join

5

Okunabilirlik için:

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

0

.NET Framework 4.5'ten başlayarak şunları kullanabilirsiniz:

using System.Threading.Tasks;

Task.Delay(50).Wait();   // wait 50ms

-1

Her iki dünyanın en iyisi:

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);
    }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.