您当前的位置: 首页 > 

君子居易

暂无认证

  • 0浏览

    0关注

    210博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Thread.Sleep 是程序设计不佳的标志。

君子居易 发布时间:2022-07-13 15:39:53 ,浏览量:0

Thread.Sleep有它的用途:在 MTA 线程上测试/调试时模拟冗长的操作。在 .NET 中没有其他理由使用它。

Thread.Sleep(n) 意味着阻塞当前线程至少在 n 毫秒内发生的时间片(或线程量子)数量。时间片的长度在不同版本/类型的 Windows 和不同的处理器上是不同的,一般在 15 到 30 毫秒之间。这意味着线程几乎可以保证阻塞超过 n 毫秒。您的线程恰好在 n 毫秒后重新唤醒的可能性几乎是不可能的。因此, Thread.Sleep 对计时毫无意义。

线程是一种有限的资源,它们需要大约 200,000 个周期来创建和大约 100,000 个周期来销毁。默认情况下,它们为其堆栈保留 1 兆字节的虚拟内存,并为每个上下文切换使用 2,000-8,000 个周期。这使得任何等待线程成为*巨大的*浪费。

如果当前线程是前台线程,Thread.Sleep(n) 也意味着您的应用程序无法退出 >n 毫秒。在所有前台线程都完成后,CLR 将允许应用程序终止。如果当前线程是后台线程,并且应用程序退出,则该线程将永远不会被唤醒(如果您需要释放或完成对象,那就不好了)。

STA 线程具有不进行阻塞调用的隐含要求。STA 线程使用消息队列(有限大小)与外界通信;无论您是否明确使用它,都会发生这种通信。当您使用 Thread.Sleep 阻止您的 STA 线程时,您将阻止该通信并冒队列溢出的风险。WinForm 线程必须是 STA,因此它具有相同的隐含要求,即不进行阻塞调用只是为了支持成为一个单元。出于显而易见的原因,GUI 永远不应进行可能影响用户界面响应能力的调用。

Thread.Sleep 有一个不间断的用途:Thread.Sleep(0)。这告诉系统你想放弃线程的剩余时间片,让另一个等待的线程运行。如果没有其他线程等待运行,您仍然会放弃您的时间片。如果还有其他线程等待运行,您将无法确定何时重新获得控制权;如果等待线程具有更高的优先级,您可能永远无法取回控制权。Thread.Sleep(0) 有效地告诉操作系统你比它更擅长调度进程,如果你使用 Sleep( 0) 很多。

随着未来版本的 CLR 和 CLR 主机的实现,它们最终将实现线程而不直接依赖于非托管线程(例如,完全由 CLR 使用纤程管理。)这意味着必须重新实现 Thread.Sleep 才能做一些不同的事情(例如即,如果 Sleep(0) 意味着将当前线程的时间片放弃给操作系统并且没有当前操作系统线程,则 Sleep(0) 意味着什么。如果没有重新实现 Thread.Sleep Thread.Thread(0) 意味着阻塞所有光纤,或托管线程,与当前操作系统线程相关联。您永远不想导致其他线程暂停,尤其是任意暂停)。因此,System.Thread 对未来不友好。

Thread.Sleep 已被用于许多不应该用于的事情。以下是常见错误列表:

线程需要等待另一个线程完成 在这种情况下,传递给 Thread.Sleep 的任何值(除了无限)都是正确的。您根本不知道其他线程何时使用此方法完成。如果线程在 Sleep 返回后完成,您可能会遇到同步问题。如果另一个线程在 Sleep 返回之前完成,则该线程被不必要地阻塞了一段时间,从而使多线程的好处受到限制或没有实际意义。在您测试过的控制环境中,它似乎总是有效;只需要一个繁忙的程序就会导致它失败:碎片整理程序、网络流量的突然涌入、网络故障等。

线程需要每 n 毫秒执行一次逻辑 如前所述,睡眠意味着放弃控制。当你的线程再次获得控制权不取决于线程;所以它不能用于周期性逻辑。

我们不知道为什么需要 Thread.Sleep;但是如果我们把它拿出来,应用程序就会停止工作 这是有缺陷的逻辑,因为应用程序仍然不能与Thread.Sleep 一起工作。这实际上只是解决了特定计算机上的问题。最初的问题可能是时间/同步问题,通过使用 Thread.Sleep 隐藏它来忽略它只会延迟问题并使其以随机、难以重现的方式发生。

关注
打赏
1660814979
查看更多评论
立即登录/注册

微信扫码登录

0.0356s