我是 C# 的新手,我正在使用 System.Threading。
我有这个代码:
UISystem.SetScene(Scene_Menu);
Thread.Sleep (9000);
p.Text="HELLO";
Thread.Sleep(9000);
p.Text="WORLD";
它延迟了 18 秒,但是 p.Text="HELLO"
在 sleep 函数之间没有显示。我的代码有什么问题?
谢谢。
计时器不工作,因为我无法从单独的线程编辑 p。
Application.DoEvents() 是一个 Windows 窗体函数,我正在 PS Vita 中构建一个应用程序。
最佳答案
您已经发现为什么永远不应该使用 Thread.Sleep。它仅对两件事有用。 (1) 编写需要模拟线程忙碌一定秒数的测试用例,以及 (2) 休眠零毫秒告诉操作系统“如果存在一个进程,我将剩余的时间片让给另一个进程想要它”;这是一种礼貌。
你永远不应该使用 thread.Sleep 来引入延迟,因为你正在做的正是你发现的原因。您正在设置属性,但设置属性不会导致操作系统重新绘制屏幕。考虑一下是否这样做;你可能在一个方法中有上千个属性集,你必须在所有这些之后重新绘制屏幕,这看起来很难看并且非常慢。
取而代之的是属性被设置并且对象向操作系统发出注释,上面写着当这个线程可以再次处理操作系统消息时,请重新绘制我。您的程序不是告诉操作系统“我完成了,继续查看是否有任何消息给我”,而是您希望线程在 9 秒内不执行任何操作。
现在,您可以通过调用 DoEvents 告诉程序检查消息,但是使用 DoEvents 也是一个坏主意,您不应该这样做。这样做本质上会导致您的程序表现出注意力缺陷障碍的症状;您还没有完成当前 的工作,并且您正在查看是否有新的工作要做,而不是从调用堆栈中删除旧的工作!假设这些新工作又被打断,依此类推。堆栈无限增长,这是非常糟糕的。 DoEvents 是一种“最坏的做法”,就像休眠线程一样。您可以在简单的小程序中避开它,但当程序变得复杂时,它会导致大麻烦。
此外:是的,DoEvents 将绘制您的控件,但这就是它的全部。在接下来的 9 秒内,应用程序将在用户看来完全挂起。这是非常糟糕的用户体验。
如果您想引入延迟,正确的做法是异步等待。在 C# 4 和更早版本中,标准方法是创建一个计时器,当计时器计时时,执行下一步。
现在,您说您不能使用计时器,因为您需要从 UI 线程访问控件。没关系。 计时器的滴答事件处理程序将在 UI 线程上运行,而不是在单独的线程上运行。您可以安全地使用计时器。
在 C# 5 中,正确的做法是使用新的 await
关键字来引入异步等待。也就是说,等待在等待的时候做其他事情,而不是在等待的时候去 sleep 。在 C# 5 中,您可以将代码编写为:
UISystem.SetScene(Scene_Menu);
await Task.Delay (9000);
p.Text="HELLO";
await Task.Delay(9000);
p.Text="WORLD";
C# 5 目前处于测试阶段;有关此新功能的详细信息,请参阅:
http://msdn.microsoft.com/en-us/async
有关异步的简要介绍以及为什么 DoEvents 是坏消息的解释,请参阅我的 MSDN 杂志文章:
关于c# - System.Threading 休眠功能有帮助吗? (C#),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10366255/