Странное поведение Thread.Sleep [дубликат]

200
26 июля 2017, 19:49

На данный вопрос уже ответили:

  • Почему Thread.Sleep ведёт себя неправильно? Как мне сделать задержку или длинные вычисления в графической программе? 2 ответа

Решил пощупать приложение с окнами, и тут возникла проблема. Есть код:

Random rnd = new Random();
 for (int i = 0; i < 9; i++)
 {
    int value = rnd.Next(1, 6);
    switch (value)
    {
      case 1:
         label3.Text = "";
         break;
      case 2:
         label3.Text = "";
         break;
      case 3:
         label3.Text = "";
         break;
      case 4:
         label3.Text = "";
         break;
      case 5:
         label3.Text = "";
         break;
    }
    Thread.Sleep(2000);
    label4.Text = Convert.ToString(i);
  }

Однако Thread.Sleep(2000); не работает. Когда я запускаю программу, она как будто игнорирует слип, и в label.4 сразу выводится 8. Почему так и как выйти из данной ситуации?

Answer 1

Ничего странного. Когда вы меняете текст надписи - ее регион в окне инвалидируется и в очередь сообщений посылается сообщение WM_PAINT. Но это сообщение может быть обработано только после того, как ваш цикл завершит работу.

Есть три способа исправить такую ситуацию. Первый - старый - вызов Application.DoEvents() внутри цикла, чтобы "разгрести" накопившиеся сообщения:

for (int i = 0; i < 9; i++)
{
  Thread.Sleep(2000);
  label4.Text = Convert.ToString(i);
  Application.DoEvents();
}

Второй способ - объявить метод асинхронным (async) и использовать await Task.Delay для ожидания:

async void button1_Click (object sender, EventArgs e) {
  for (int i = 0; i < 9; i++)
  {
    await Task.Delay(2000);
    label4.Text = Convert.ToString(i);
  }
}

Не забудьте только установить обработчик события Application.ThreadException при использовании async void-метода.

Третий способ - можно вынести цикл в отдельный поток.

READ ALSO
Помогите разобраться С#!

Помогите разобраться С#!

Получается такЕсли вывожу

201
Компилятор игнорирует Url.Action [требует правки]

Компилятор игнорирует Url.Action [требует правки]

При попытки вывести изображение из бд в представлении, компилятор не попадает в метод GetImage(), то бишь он не заходит в строку 33Если поставить...

217
Как запретить двигать консоль

Как запретить двигать консоль

Какими средствами WinAPI можно заблокировать перемещение окна консоли?

260