C#winform闪烁标签背景颜色有延迟

时间:2015-01-08 18:50:41

标签: c# windows multithreading timer task

我有一个winform应用程序,我需要使标签背面闪烁。我试图使用for循环和Thread.Sleep,但不起作用。感谢您的帮助和建议:

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;
    }
}   

2 个答案:

答案 0 :(得分:5)

使用UI计时器,而不是为此任务休眠。您始终将主线程置于休眠状态,并且您将阻止用户输入。使用Thread.Sleep 几乎总是表示您做错了。 Thread.Sleep正确的情况非常少。具体来说,将UI线程置于休眠状态永远不会正确。

在表单上放置Timer组件,在Tick事件中,不断更改标签的背景颜色。

例如:

// 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 ();
}

答案 1 :(得分:0)

这里发生的是你正在睡觉的GUI线程,导致程序挂起。 GUI线程也是负责更改标签背景颜色的线程。

这是一个简单的实现,可以为您解决此问题。请注意,这不是最佳实现,但它使用您首选的闪烁代码实现。有关比Thread.Sleep更好的选项,请参阅System.Timers.Timer,或者,如xxbbcc建议的那样,请参阅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();
        }
    }