我是 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 是“最糟糕的做法”,就像 sleep 线程一样。您可以在简单的小程序中摆脱它,但是当程序变得复杂时,它会导致大麻烦。

此外:是的,DoEvents 将绘制您的控件,但这就是它所能做的。在接下来的九秒内,应用程序将在用户看来完全挂起。这是非常糟糕的用户体验。

如果您想引入延迟,正确的做法是异步等待。在 C# 4 及更早版本中,执行此操作的标准方法是创建一个计时器,并在计时器计时时执行下一步操作。

现在,您说您不能使用计时器,因为您需要从 UI 线程访问控件。没关系。 计时器的滴答事件处理程序将在 UI 线程上运行,而不是在单独的线程上运行。 您可以安全地使用计时器。

在 C# 5 中,正确的做法是使用新的 await 关键字来引入异步等待。也就是说,一个等待在等待时做其他事情,而不是在等待时进入休眠状态。在 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 杂志文章:

http://msdn.microsoft.com/en-us/magazine/hh456401.aspx

关于c# - System.Threading sleep 功能有帮助吗? (C#),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10366255/

10-16 09:17