我们做这么一个假设哈。
如果有一个线程,它拥有一个窗口,则在这个线程的整个运行过程中,我们都不应该调用 Sleep 函数。为什么?
因为 Sleep 调用会导致线程在睡眠等待期停止处理窗口消息。即使对于持续时间较短的睡眠也是如此,例如睡眠几秒钟和醒来以轮询系统中某些内容的状态。
如我之前在另一篇文章中所提到的,轮询会降低系统性能,还会损害系统在低功耗情况下节省能源的能力,并受到终端服务器的放大效应的影响。
如果当前处理器处于空闲状态,那就继续保持闲着。如果处理器很忙,那就赶紧让它完成计算任务,然后重新回到空闲状态。
但有时候我还是会看到如下的代码:
>> 请移步至 topomel.com 以查看图片 <<
请注意,此消息循环长达两秒钟而不处理消息。人们通常不会将两秒钟的睡眠插入负责与最终用户交互的线程中,但他们经常为后台工作线程执行此操作,这些线程为跨线程通信目的创建了隐藏窗口。由于线程没有可见的 UI,因此将最终用户一次挂起几秒钟是不会有明显的感知的。
但是,存在某些特殊情况。
如果系统需要广播消息,则必须等待此休眠线程最终唤醒并处理广播消息。同时,发出广播的组件继续等待。例如,用户可能双击了需要 DDE 才能打开的文档。DDE 过程从广播 WM_DDE_INITIATE 消息开始,该消息停滞在窗口后面。你的无响应隐藏窗口刚刚创建了一个 “Windows 似乎以随机间隔挂起几秒钟” 错误。
请注意,许多人忽略了调用 CoInitialize(可能间接)来初始化 STA 的线程会创建一个隐藏窗口以执行列集。因此,在单线程单元中运行的线程必须不停地处理消息。如果不这样做,由于窗口无响应,将导致神秘的系统级卡顿。
总结
对于在用户界面线程中执行的代码,我的观点是:不是非常必要,都不要使用 Sleep。
人的生命是有限的,软件运行的快,是一个终极需求。
最后
Raymond Chen的《The Old New Thing》是我非常喜欢的博客之一,里面有很多关于Windows的小知识,对于广大Windows平台开发者来说,确实十分有帮助。
本文来自:《The dangers of sleeping on a UI thread》