【问题标题】:Thread.Sleep not working as I would expect in C#Thread.Sleep 没有像我在 C# 中所期望的那样工作
【发布时间】:2018-11-11 22:17:32
【问题描述】:

此代码模仿了我在应用中遇到的问题。

    private void button1_Click(object sender, EventArgs e)
    {
        button1.BackColor = Color.Red;
        Thread.Sleep(3000);
        button1.BackColor = Color.Green;
    }

我希望这段代码能够;

  • 将按钮设为红色
  • 等待 3 秒
  • 将按钮设为绿色

但它正在等待 3 秒,然后将按钮变为绿色。我不能从一开始就将按钮设为绿色,因为这在我更大的应用程序中不起作用。

有谁知道出了什么问题以及我该如何解决?提前致谢。

【问题讨论】:

  • 您的 GUI 线程没有机会更新 UI 以使用红色。尝试使用异步编程模型和 Task.Delay。现在只需在 3 秒睡眠之前添加一个 Thread.Sleep(0) 。我认为这应该可行。
  • 绘制屏幕不会立即发生,它作为事件队列中的事件发生。只有在您从当前事件返回后才会处理事件。所以按钮认为它是红色的,但它永远无法绘制到屏幕上,因为你没有返回,并给“绘制”事件一个机会。

标签: c# thread-sleep


【解决方案1】:

没有。它正在更改为红色,但您正在阻止您的 UI 线程,因此您看不到颜色发生了变化。如果您将处理程序更改为async 类似

private async Task button1_Click(object sender, EventArgs e)
{
    button1.BackColor = Color.Red;
    await Task.Delay(3000);
    button1.BackColor = Color.Green;
}

【讨论】:

    【解决方案2】:

    问题在于,使用 Sleep 会阻塞主(渲染)线程。因此,您将按钮设置为红色,但是由于您阻塞了线程,因此应用程序无法呈现它。事实上,我希望整个应用程序冻结。
    我不确定您使用的是什么,但请尝试查看一些计时器。

    编辑或简单地使用任务Delayed function calls。请不要使用线程。

    【讨论】:

      【解决方案3】:

      这样做的技术原因是 UI 在消息泵上工作(在 WinForms 的情况下,或在 WPF 方面类似的情况下)。基本上,消息泵是要执行的工作项队列,以及如下所示的 while 循环:

      while(GetMessage(&msg, NULL, 0, 0) > 0) 
      { 
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
      }
      

      发生了什么,当您处理点击时:

      1. 点击进入消息队列
      2. 由消息泵处理
      3. 进入你的点击方法
      4. 将线程阻塞 x 秒,它仍在您的方法中,并且泵无法处理。

      为什么?

      Thread.Sleep()

      暂停当前线程指定的时间。

      简而言之,不会处理其他消息。在您的示例中,您在泵有时间处理您的颜色更改之前休眠线程(它仍然坚持处理您的点击)。

      当消息最终处理时,它会通过积压(您的颜色更改是其中的一部分),然后毫不犹豫地快速将其从一个更改为另一个。

      修复非常简单,您需要让泵在等待时处理消息,并且由于其他答案无法解决,在 .net 上的现代版本中,我们可以使用 async await 模式,并采取Task.Delay() 方法的优势。

      当程序处理任何以await为前缀的东西时,

      1. 如果您在 UI 线程上,它会捕获上下文
      2. 启动另一个线程并继续,
      3. 让消息泵继续处理。
      4. 当任务完成(并且您的延迟结束)时,它会将控制权返回到原始上下文(您从中调用它的线程)。

      嘿,转眼间。一切都应该如此。

      【讨论】:

        猜你喜欢
        • 2016-12-03
        • 1970-01-01
        • 2020-07-27
        • 2019-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多