C#Windows窗体Thread.Sleep()不起作用?

时间:2017-11-11 08:18:03

标签: c# winforms

 switch (Pattern[i])
        {
            case "Blue":
                blueButton.BackColor = Color.LightBlue;
                Thread.Sleep(1000);
                blueButton.BackColor = Color.Red;
                break;
            case "Lime":
                limeButton.BackColor = Color.Aquamarine;
                Thread.Sleep(1000);
                limeButton.BackColor = Color.Red;
                break;
            case "Yellow":
                yellowButton.BackColor = ColorTranslator.FromHtml("#FFFF80");
                Task.Delay(1000).Wait();
                yellowButton.BackColor = Color.Red;
                break;
            case "Red":
                redButton.BackColor = Color.Pink;
                Task.Delay(1000);
                redButton.BackColor = Color.Red;
                break;
        }    

但是没有延迟......它只是跳过了。我尝试使用Task.Delay和Thread.Sleep,但实际上没有延迟。我也是一名新程序员,所以请放轻松。

2 个答案:

答案 0 :(得分:2)

Thread.Sleep会按预期延迟执行,但是您在打印UI的同一个线程上运行此代码,因此没有可见的更新。

一个简单的解决方法是Task.Delay(您需要将该功能标记为async):

 case "Blue":
     blueButton.BackColor = Color.LightBlue;
     await Task.Delay(1000);
     blueButton.BackColor = Color.Red;
     break;

要将函数标记为异步,请将async关键字添加到函数调用

 private async Task showPattern(List<string> Pattern)

您应该阅读有关Windows GUI线程和async programming的一些基础知识。

UI线程的一个非常基本的解释: 当您调用Form.ShowForm.ShowDialog时,应用程序正在启动所谓的消息循环。此消息循环确实处理所显示窗口的鼠标和键盘事件。此消息循环还处理窗口的绘制。因此,如果此线程被锁定,您的应用程序将无响应。 Button Click处理程序(以及Window的所有其他处理程序)由同一个Thread处理。如果您在其中一个处理程序中阻止执行(就像使用Thread.Delay那样),则此时窗口无响应(不处理事件而不是重绘)。

要解决此问题,一种解决方案是使用asyncawait? 。这两种方法做了很多编译器魔术,使得这项工作正如人们所期望的那样(查看链接以获取更多信息,你绝对应该!)

答案 1 :(得分:0)

重现与你的相同的场景有点困难,但在这里我做了一个小尝试来测试你的问题,并且这样做有效。为简单起见,我只使用一个按钮,并通过从组合框切换选定的值来执行所有操作。它将颜色转换为指定的颜色,然后在一秒钟后转换为红色。我会尽快发布一个gif。

enter image description here

你的代码就像一个魅力!我建议检查其他控件或切换变量。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {

            String color = this.comboBox1.SelectedItem.ToString();

            switch (color)
            {
                case "Blue":
                    button1.BackColor = Color.LightBlue;
                    Thread.Sleep(1000);
                    button1.BackColor = Color.Red;
                    break;
                case "Lime":
                    button1.BackColor = Color.Aquamarine;
                    Thread.Sleep(1000);
                    button1.BackColor = Color.Red;
                    break;
                case "Yellow":
                    button1.BackColor = ColorTranslator.FromHtml("#FFFF80");
                    Task.Delay(1000).Wait();
                    button1.BackColor = Color.Red;
                    break;
                case "Red":
                    button1.BackColor = Color.Pink;
                    Task.Delay(1000);
                    button1.BackColor = Color.Red;
                    break;
            }
        }
    }
}