【问题标题】:Does usage of Thread.Sleep(n) causes performance issues?使用 Thread.Sleep(n) 会导致性能问题吗?
【发布时间】:2014-01-23 13:58:21
【问题描述】:

我正在为我的项目使用 Thread.Sleep(n)。我听说 Thread.Sleep 会导致性能问题,但不确定。

我的要求是:

等待 5 分钟增量,最多 30 分钟(5 分钟的 6 倍) 延迟)。在此之后,开始增加 1 小时并执行 5 次 (额外 5 小时)。

下面我提供了在不同场景中使用 Thread.Sleep(n) 的示例代码:

Thread.Sleep(1000 * 60 * 5); //-------waiting for 5 minutes
var isDownloaded = false;
try
{
    var attempt = 0;
    while (attempt < 11)
    {
        isDownloaded = TryDownloading(strPathToDownload, strFileToDownload);
        if (isDownloaded)
            break;
        attempt++;
        if (attempt < 6)
            Thread.Sleep(1000 * 60 * 5); //--------waiting for 5 minutes
        else
        {
            if (attempt < 11)
                Thread.Sleep(1000 * 60 * 60); //-------waiting for 1 hour
            else
                break;
        }
    }

}

在上面的代码中,我尝试下载一个最多 11 次下载尝试的文件。最初它会等待 5 分钟,然后尝试下载文件,这是 第一次尝试,如果失败则尝试 接下来 5 次尝试,每次尝试间隔 5 分钟 .如果前六次尝试失败,则接下来的 5 次尝试以 1 小时的间隔进行

所以我们决定在控制台应用程序中使用 Thread.Sleep 来处理这些时间延迟。

这会导致任何问题或性能问题吗?

如果 Thread.Sleep(n) 导致性能问题,那么与使用 Thread.Sleep(n) 相比,哪种方法更好?

最后,MSDN 是否建议 Thread.Sleep(n) 有害或不应该使用?

【问题讨论】:

  • 这是有害的,因为你不能中止它。它将使用池中的线程来处理 Web 应用程序请求
  • 听起来你应该有一个单独的进程,并使用操作系统来安排它。
  • 没有迹象表明 ASP.NET 是如何参与的,所以我删除了对它的引用。如果您在系统中的某个位置使用 ASP.NET,您应该指出它的重要性。
  • @Gabe 感谢您编辑它..
  • 你会雇人做一份工作,然后付钱让他们睡觉吗?这听起来像是计时器或其他调度机制的工作。

标签: c# multithreading


【解决方案1】:

这绝对没问题。以下是睡觉的费用:

  • 您保持线程被占用。这需要一点记忆。
  • 在操作系统内部设置等待。那是O(1)。睡眠的持续时间无关紧要。这是一笔很小的固定成本。

就是这样。

不过,糟糕的是忙于等待或进行轮询循环,因为这会导致实际的 CPU 使用率。只是在睡眠或等待中花费时间不会增加 CPU 使用率。

TL;DR:使用 sleep 进行延迟,不要使用 sleep 进行轮询。

我必须说,对睡眠的厌恶有时只是一种训练有素的反射。在谴责睡眠之前,请务必分析具体的用例。

【讨论】:

  • 这是睡眠三段论:“睡眠调用用于线程间轮询循环。线程间通信轮询循环很糟糕,因为 CPU/内存带宽浪费和可避免的延迟。所以,睡眠很糟糕并且绝对不能使用”。这个废话重复了很多次,以至于开发人员都相信了。
【解决方案2】:

不要使用 ASP.NET 工作进程来运行长时间运行的任务!

应用程序池随时可能被回收,您将失去睡眠线程。

考虑改用 Windows 服务。 您可以使用数据库或消息传递在网站和 Windows 服务之间进行通信。

【讨论】:

  • 虽然这是真的,但他确实说:“所以我们决定在我们的控制台应用程序中使用 Thread.Sleep 来解决这些时间延迟问题。” (我的重点)。
【解决方案3】:

您最好使用 Timer 来执行此类间歇性操作,因为 Thread.Sleep 是一个阻塞调用,会保持进程分配和应用程序冻结。

像这样: 在调用者对象中

Timer t = new Timer(1000 * 60 * 5);
t.Tick += t_Tick;
t.Start(); 

比实现事件

//event timer elapsed implementation
int count = 0;
 private void t_Tick(object sender, EventArgs e)
 {
  if(count >=5)
  t.Stop();
  else{
  //your code that do the work here
  }

【讨论】:

  • 不,它没有。 Thread.Sleep 不会冻结应用程序,它会在指定的时间间隔内阻止调用 THREAD。当然,在应该处理 GUI 消息的线程中不当使用此类阻塞调用会导致 GUI 停止,但是 OP 认为他/她正在开发控制台应用程序,无论如何,只是因为应用程序具有 GUI 并不意味着它只有一个线程 - 具有 GUI 界面的应用程序可能有其他指定延迟的线程。
  • 当然,如果您在主 ui 线程中调用 Sleep 应用程序将冻结。否则不要。
猜你喜欢
  • 2015-02-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-10
  • 1970-01-01
相关资源
最近更新 更多