Как заставить мою программу C # спать 50 мс?


272

Как мне заставить мою программу на C # спать 50 миллисекунд?

Это может показаться простым вопросом, но у меня временная остановка мозга!


1
Повторно помечен на VB.NET, так как там тоже работает ответ.
DrFloyd5

Нет DrFloyd5,; не работает в VB.NET, верно?
Занони

16
Если бы я был в команде VB.Net, я бы добавил; в качестве комментария к следующей версии языка ...
Джоэл Кохорн

4
Я думаю, что программисты VB достаточно
умны

ну, просто чтобы убедиться, теперь они не должны.
PsychoData

Ответы:


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

Помните, однако, что выполнение этого в основном потоке GUI заблокирует обновление вашего GUI (оно будет выглядеть «вялым»)

Просто удалите ; чтобы он работал и для VB.net.


После вызова sleep в методе программа продолжит выполнение в фоновом режиме (без создания нового потока)? Кроме того, если я вызову sleep в новом потоке, продолжит ли основной поток свою работу?
Джей Ниргудкар

@JayNirgudkar поток, который вызывает Sleep, будет остановлен. Другие темы не затрагиваются.
Исак Саво

Это не гарантируется, чтобы быть точным.
Акумаберн

150

Есть в основном 3 варианта ожидания на (почти) любом языке программирования:

  1. Бесполезное ожидание
    • Выполнение потоковых блоков в течение заданного времени (= не потребляет вычислительной мощности)
    • Обработка невозможна в заблокированном / ожидающем потоке
    • Не так точно
  2. Тугое ожидание (также называется тугой петлей)
    • Процессор ОЧЕНЬ занят в течение всего интервала ожидания (фактически он обычно потребляет 100% времени обработки одного ядра)
    • Некоторые действия могут быть выполнены во время ожидания
    • Очень точный
  3. Сочетание предыдущих 2
    • Обычно он сочетает в себе эффективность обработки 1 и точность + способность делать что-то 2.

для 1. - Слабое ожидание в C #:

Thread.Sleep(numberOfMilliseconds);

Тем не менее, планировщик потока Windows вызывает точность Sleep() к тому, что точность составляет около 15 мс (так что Sleep может легко ждать 20 мс, даже если запланировано ожидание только 1 мс).

для 2. - Тесное ожидание в C # - это:

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

Мы могли бы также использовать DateTime.Nowили другие средства измерения времени, но Stopwatchгораздо быстрее (и это действительно стало бы видно в тесной петле).

для 3. - Комбинация:

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
}

Этот код регулярно блокирует поток на 1 мс (или чуть больше, в зависимости от планирования потоков ОС), поэтому процессор не занят в это время блокировки и код не потребляет 100% мощности процессора. Между ними может выполняться другая обработка (например, обновление пользовательского интерфейса, обработка событий или выполнение взаимодействия / взаимодействия).


1
Таймер также может представлять интерес
JonnyRaa

55

Вы не можете указать точное время сна в Windows. Для этого вам нужна ОС реального времени. Лучшее, что вы можете сделать, это указать минимальное время сна. Тогда это до планировщика, чтобы разбудить Ваш поток после этого. И никогда не вызывайте .Sleep()на поток GUI.


44

Поскольку теперь у вас есть функция async / await, лучший способ спать в течение 50 мс - использовать Task.Delay:

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

Или, если вы ориентируетесь на .NET 4 (с Async CTP 3 для VS2010 или Microsoft.Bcl.Async), вы должны использовать:

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

Таким образом, вы не будете блокировать поток пользовательского интерфейса.


Можете ли вы response.flush во время этой задержки, если она находится в цикле?
Теоман Шипахи

Нет, ты не можешь. Я верю, что есть FlushAsyncверсия.
Тони Петрина

6
Альтернативой, которая не требует asyncобъявления, является вызовTask.Delay(50).Wait();
stuartd


14
Thread.Sleep(50);

Поток не будет запланирован для выполнения операционной системой в течение указанного времени. Этот метод изменяет состояние потока, чтобы включить WaitSleepJoin.

Этот метод не выполняет стандартную перекачку COM и SendMessage. Если вам нужно спать в потоке с атрибутом STAThreadAttribute, но вы хотите выполнить стандартную откачку COM и SendMessage, рассмотрите возможность использования одной из перегрузок метода Join, которая задает интервал времени ожидания.

Thread.Join


0

Начиная с .NET Framework 4.5, вы можете использовать:

using System.Threading.Tasks;

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

-1

Лучшее из обоих миров:

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);
    }
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.