睡觉不按预期行事

时间:2013-12-17 12:39:44

标签: c# .net wpf

我有一个WPF应用程序,我想在屏幕上显示某些信息之前睡一会儿。所以这是。 1.单击按钮。

  1. 睡1秒
  2. 显示标签。
  3. 睡1秒
  4. 显示标签。
  5. 等等

    private void RunTest()
    {
        clearTable();
    
        System.Threading.Thread.Sleep(1000);
    
        this.Cursor = Cursors.Wait;
    
        Label_OS_Result.Content = operatingSystem;
        Image_OS.Visibility = Visibility.Visible;
    
        System.Threading.Thread.Sleep(1000);
    
        Label_CPU_Result.Content = procName;
        Image_CPU.Visibility = Visibility.Visible;
    
        System.Threading.Thread.Sleep(1000);
     }
    
  6. 但是当我点击我的按钮时,它似乎等了几秒钟,然后一次显示所有内容。

    这是怎么回事?

4 个答案:

答案 0 :(得分:1)

它按预期工作。

Thread.Sleep停止执行当前线程达指定的时间。因此,当您更改图像的可见性时,它将进一步调用以更改框架中的可见性,然后它将尝试在屏幕上绘制它(无效)。在此操作完成之前休眠线程时,它将没有足够的时间来完成此操作。您只是阻止负责在屏幕上绘制内容的UI线程。

请注意Thread.Sleep可能不是解决方案,最好是查看DispatcherTimer或BackgroundWorkers。

答案 1 :(得分:1)

您不希望在显示GUI的线程上Thead.Sleep()

相反,您应该尝试await Task.Delay()。这类似于sleep,但它不会阻止GUI线程。

这将允许所有渲染仍然发生,同时延迟标签的可见性更改。

答案 2 :(得分:1)

它按预期工作。

这可能不是您的预期,但问题在于您的期望。

当您在大多数可视控件上调整属性时会发生什么,最终应该更改控件​​的外观,首先要对控件属性(即数据)进行内部调整,然后触发重绘。要触发重绘,通常会将消息发布到拥有此可视控件的线程的消息队列中。

此线程通常一次处理一个消息,无论是单击按钮,鼠标移动还是因为您更改了图像而刚刚发布的绘制消息。

但是,该线程基本上是这样编写的(伪代码):

while (true)
{
    var message = GetNextMessageFromQueue();
    ProcessMessage(message);
}

这个循环最后一次激活时,它开始处理一条消息,最后调用你的代码,现在正在睡觉。

所以基本上,要获取消息泵(实现此循环的代码的典型名称)来继续泵送消息,从而处理您的绘制消息,不要睡觉。

您可能希望将处理分离到不同的线程,或者“在后台”执行某些其他异步处理方式。

请注意,如果您在响应按钮单击或类似操作时开始执行任何类型的冗长处理,而不在后台线程上执行(或者再次使用其他异步方式),则会遇到相同的问题。 GUI似乎已冻结。

然而,这个问题非常普遍,微软最终在Windows中建立了对它的特殊支持。曾经是一个窗口似乎挂起了。但是,现在,如果消息队列“填满”,Windows将淡出窗口并添加一个标题,指示它已停止响应。不是解决方案,但稍好一点。

答案 3 :(得分:0)

睡眠功能表现正确。

最好使用Timer来执行此操作,

    // Declare it in the constructor of the class
    int level = 0;
    Timer timer = new Timer
    timer.Interval = 1000;
    timer.Tick +=new EventHandler(timer_Tick);

private void timer_Tick(object sender, EventArgs e)
{
    timer.Stop();
    if (level == 0)
    {
        Label_OS_Result.Content = operatingSystem;
        Image_OS.Visibility = Visibility.Visible;
        ++level;
    }
    else if (level == 1)
    {
        Label_CPU_Result.Content = procName;
        Image_CPU.Visibility = Visibility.Visible;
        ++level;
    }
    else if (level > 1)
    {
        this.Cursor = Cursors.Default;
        return;
    }
    timer.Start();
}
private void RunTest()
{
    clearTable();

    //System.Threading.Thread.Sleep(1000);
    timer.Start();
    this.Cursor = Cursors.Wait;
}