Кнопка не меняет свой цвет

Подскажите плиз, почему кнопки не мигают как задумано (т.е. мигнула - задержка, снова мигнула другим цветом, и далее по циклу

for (int i=0; i<3; i++)
 {
   button.BackColor = Color.Black;
   System.Threading.Thread.Sleep(1000);
   button.BackColor = Color.White;
   System.Threading.Thread.Sleep(1000);
 }

Ответы (2 шт):

Автор решения: aepot

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

В самом начале кода добавьте

using System.Threading;

Рядом с такими же юзингами, чтобы не повторять System.Threading в коде.

Затем

for (int i=0; i<3; i++)
{
   button.BackColor = Color.Black;
   Application.DoEvents();
   Thread.Sleep(1000);
   button.BackColor = Color.White;
   Application.DoEvents();
   Thread.Sleep(1000);
}

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

Есть и другие способы решения этой задачи - асинхронность (async/await) и многопоточность (Task). Но тема сложная и обширная.

Вот пример с асинхронностью.

private async Task ButtonFlashAsync()
{
    for (int i = 0; i < 100; i++)
    {
        button2.BackColor = Color.Black;
        await Task.Delay(75);
        button2.BackColor = Color.White;
        await Task.Delay(75);
    }
}

private async void button1_Click(object sender, EventArgs e)
{
    button2.Text = "Begin";
    await ButtonFlashAsync();
    button2.Text = "Finish";
}
→ Ссылка
Автор решения: Евгений Марков

Ок, раз DoEvents - это плохо, по совету aepot попробовал сделать это через async / await Вроде работает

public void Buttonflash()
        {
            for (int i = 0; i < 100; i++)
            {
                button2.BackColor = Color.Black;
                Thread.Sleep(75);
                button2.BackColor = Color.White;
                Thread.Sleep(75);
            }
        }
        public async void TestAsync()
        {
            button2.Text = "Begin";
            await Task.Run(()=> Buttonflash());
            button2.Text = "Finish";
        }

        private void button1_Click(object sender, EventArgs e)
        {
            TestAsync();
        }
→ Ссылка