-3

可能重复:
为什么 Thread.sleep() 会以这种方式运行

这是我写的一个简单的代码:

    private void button1_Click(object sender, EventArgs e)
    {
        label1.Text = "first";
        Thread.Sleep(1000);
        label1.Text = "second";
    }

执行此代码并单击按钮时,label1 仅将文本显示为“第二”而不是“第一”。我使用断点检查,语句 label1.text="first" 被执行但标签不显示'first'。为什么会这样?

4

4 回答 4

3

因为您的代码在 UI 线程上运行。

当您的应用程序正在运行并且您没有点击任何东西时,应用程序的主线程会四处奔波,等待事件,处理 Windows 消息并绘制屏幕。当您单击按钮时,应用程序会停止执行这些操作,而是运行您的函数。在运行您的方法时,它无法绘制屏幕。您的函数将标签设置为“第一”,将线程阻塞一秒钟,然后将标签设置为“第二”。

当您返回时,控制权会传回给应用程序,然后应用程序可以自由地重新绘制表单。它使用“第二个”标签重新绘制它。消息循环从来没有机会用“第一个”标签来绘制它。

于 2012-07-20T10:21:49.463 回答
3

您正在运行一个单线程应用程序。虽然将 label1 对象的 Text 属性设置为“first”的语句已被执行,但由于您正在导致主应用程序线程暂停,“Windows 消息泵”并未被执行。

于 2012-07-20T10:24:41.503 回答
1

问题是您在这里冻结了 UI 线程。

文本“first”已设置,但随后您将主 GUI 线程置于睡眠状态 - 因此 UI 不会被绘制。

睡眠阶段结束后,设置文本“second”并绘制 UI。

这正是 Windows 的工作方式,因此您必须以不同的方式进行操作。例如使用线程或Backgroundworker

于 2012-07-20T10:21:30.140 回答
0

如果你想延迟使用计时器。

在 UI 中看不到结果的原因是因为 Dipatcher 的优先级。渲染任务的优先级低于执行。

这可以帮助您:计时器!

DispatcherTimer dispatcherTimer = new DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 1);
dispatcherTimer.Start();

private void dispatcherTimer_Tick(object sender, EventArgs e)
{
//your code goes here
}

如果你在 WPF 中工作,你可以试试这个:

private void button1_Click(object sender, RoutedEventArgs e)
{
    label1.Text = "first";
    Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle);
    Thread.Sleep(1000);                            
    label1.Text = "second";
}
于 2012-07-20T10:21:00.533 回答