Thread.Sleep не работает, как я ожидал в C # - PullRequest
0 голосов
/ 12 ноября 2018

Этот код имитирует проблему, с которой я сталкиваюсь в своем приложении.

    private void button1_Click(object sender, EventArgs e)
    {
        button1.BackColor = Color.Red;
        Thread.Sleep(3000);
        button1.BackColor = Color.Green;
    }

Я бы ожидал, что этот код;

  • Сделать кнопку красной
  • Подождите 3 с
  • Сделать кнопку зеленой

но вместо этого он ждет 3 секунды и затем делает кнопку зеленой. Я не могу просто сделать зеленую кнопку с самого начала, так как это не сработает в моем большом приложении.

Кто-нибудь знает, что не так, а также как я мог это исправить? Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 12 ноября 2018

Нет. он меняется на красный, но вы блокируете нить пользовательского интерфейса и, следовательно, не видите изменения цвета. Что если вы измените обработчик на async такой, как

private async Task button1_Click(object sender, EventArgs e)
{
    button1.BackColor = Color.Red;
    await Task.Delay(3000);
    button1.BackColor = Color.Green;
}
0 голосов
/ 12 ноября 2018

Техническая причина для этого заключается в том, что пользовательский интерфейс работает с Message Pumps (в случае WinForms или аналогичным в отношении WPF).По сути, насос сообщений - это очередь рабочих элементов, которую необходимо выполнить, и цикл while, подобный следующему

while(GetMessage(&msg, NULL, 0, 0) > 0) 
{ 
  TranslateMessage(&msg); 
  DispatchMessage(&msg); 
}

. Что происходит, когда вы обрабатываете свой щелчок

  1. Клик попадает в очередь сообщений
  2. Получает обработанный насос сообщений
  3. Идет в ваш метод клика
  4. Блокирует поток на х секунд, он все еще в вашем методеи насос не может обработать.

Почему?

Thread.Sleep ()

Приостановляет текущую нить в течение указанного периода времени.

Короче говоря, другие сообщения не обрабатываются.В вашем примере вы засыпаете нить, пока насос еще не успел обработать ваше изменение цвета (он продолжает обрабатывать ваш щелчок).

Когда сообщения в конечном итоге обрабатываются, оно проходит через отставание (ваш цвет меняетсячасть этого), а затем без паузы быстро меняет его с одного на другое.

Исправление довольно простое, вам нужно разрешить насосу обрабатывать сообщения, пока вы ожидаете, и как другие ответы ускользнули,в современной версии .net мы можем использовать шаблон async await и использовать метод Task.Delay().

Когда программа обрабатывает все, что имеет префикс await,

  1. Если вы находитесь в потоке пользовательского интерфейса, он захватывает контекст
  2. Запуск другого потока с продолжением,
  3. позволяет обработчику сообщений продолжить обработку.
  4. Когда задача завершена (и ваша задержка закончена), она возвращает управление обратно в исходный контекст (поток, из которого вы его вызвали).

Привет, presto.Все как и должно быть

0 голосов
/ 12 ноября 2018

Проблема в том, что с помощью Sleep вы блокируете основной (рендеринг) поток. Таким образом, вы устанавливаете красную кнопку, но поскольку вы блокируете поток, приложение не может отобразить ее. На самом деле, я ожидаю, что все приложение зависнет.
Я не уверен, что вы используете, но попробуйте взглянуть на некоторые таймеры.

РЕДАКТИРОВАТЬ или просто использовать задачи Задержанные вызовы функций . Только не используйте темы, пожалуйста.

...