Doro
Doro

Reputation: 671

C# winform blink label backcolor with delay

I have a winform application and I need to make the label backcolor blinking. I am trying to do that using a for loop and a Thread.Sleep, but does not work. Thank you for any help and advise:

private void button1_Click(object sender, EventArgs e)
{
    for (int i = 0; i < 10; i++)
    {
        System.Threading.Thread.Sleep(1000); // Set fast to slow.
        if (label1.BackColor == Color.Red)
            label1.BackColor = Color.Transparent;
        else
            label1.BackColor = Color.Red;
    }
}   

Upvotes: 2

Views: 8143

Answers (2)

Zak A. Klajda
Zak A. Klajda

Reputation: 291

What's happening here is that you are sleeping the GUI thread, which causes the program to hang. The GUI thread is also the thread that would be responsible for changing the background color of the label.

Here's a simple implementation that will solve this problem for you. Note that this isn't the best implementation possible, but it uses your preferred blink code implementation. For a better option than Thread.Sleep, see System.Timers.Timer or, as xxbbcc suggested, a System.Windows.Forms.Timer.

    BackgroundWorker blinker;

    public Form1()
    {
        InitializeComponent();
        blinker = new BackgroundWorker();
        blinker.DoWork += blinker_DoWork;
    }

    private void blinker_DoWork(object sender, DoWorkEventArgs e)
    {
        for (int i = 0; i < 10; i++)
        {
            System.Threading.Thread.Sleep(1000); // Set fast to slow.

            if (label1.InvokeRequired)
            {
                label1.Invoke((Action)blink);
            }
            else
            {
                blink();
            }
        }
    }

    private void blink()
    {
        if (label1.BackColor == Color.Red)
            label1.BackColor = Color.Transparent;
        else
            label1.BackColor = Color.Red;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        if (blinker.IsBusy == false)
        {
            blinker.RunWorkerAsync();
        }
    }

Upvotes: 1

xxbbcc
xxbbcc

Reputation: 17346

Use a UI timer, not sleep for this task. You're putting the main thread to sleep all the time and you're blocking user input with that. Using Thread.Sleep is almost always a sign that you're doing something wrong. There are very few situations when Thread.Sleep is correct. Specifically, putting the UI thread to sleep is never correct.

Put a Timer component on your form and in the Tick event, keep changing the background color of your label.

For example:

// Keeps track of the number of blinks
private int m_nBlinkCount = 0;

// ...

// tmrTimer is a component added to the form.
tmrTimer.Tick += new EventHandler(OnTimerTick);

m_nBlinkCount = 0;
tmrTimer.Interval = 1000; // 1 second interval
tmrTimer.Start();

// ...

private void OnTimerTick ( Object sender, EventArgs eventargs)
{
    if (label1.BackColor == Color.Red)
        label1.BackColor = Color.Transparent;
    else
        label1.BackColor = Color.Red;

    m_nBlinkCount++;

    if ( m_nBlinkCount >= 10 )
        tmrTimer.Stop ();
}

Upvotes: 6

Related Questions