【问题标题】:Purpose of Thread.Sleep(1)?Thread.Sleep(1) 的用途?
【发布时间】:2011-12-19 23:30:25
【问题描述】:

我正在阅读一些线程基础知识,并在 msdn 网站上找到了这个 sn-p 代码。

    // Put the main thread to sleep for 1 millisecond to
    // allow the worker thread to do some work:
    Thread.Sleep(1);

这是该页面的链接:http://msdn.microsoft.com/en-us/library/7a2f3ay4(v=vs.80).aspx

为什么主线程会休眠1毫秒?如果主线程一直在运行,辅助线程会不会启动它的任务?还是该示例适用于需要 1 毫秒才能完成的任务?好像任务一般需要 5 秒才能完成,主线程应该休眠 5000 毫秒?

如果这仅仅是关于 CPU 使用率,这里有一个类似的Question about Thread.Sleep

任何 cmets 将不胜感激。

谢谢。

【问题讨论】:

标签: c# multithreading


【解决方案1】:

该代码中的1 并不是很特别;它总是最终会比这更长的睡眠时间,因为事情并不那么精确,并且放弃你的时间片并不等于操作系统的任何保证你什么时候能把它拿回来。

Thread.Sleep() 中的 time 参数的目的是,您的线程将在 至少 大致的时间内屈服。

所以该代码只是明确地放弃了它的时间段。一般来说,这样的代码应该是不需要的,因为操作系统会为你管理你的线程,抢先中断它们在其他线程上工作。

这种代码通常用于“线程示例”中,作者希望强制一些人为事件来证明某些竞争条件等(在您的示例中似乎就是这种情况)


正如 Jon Hanna 对同一问题的回答中所述,Sleep(0)Sleep(1)(或任何其他非零数字)之间存在细微但重要的区别,正如 ChrisF 所暗示的那样,这在一些线程情况。

这两个都涉及线程优先级;线程可以被赋予更高/更低的优先级,这样低优先级的线程将永远执行,只要有更高优先级的线程有任何工作要做。在这种情况下,可能需要Sleep(1)... 但是...

低优先级线程也受制于同一系统上其他进程正在执行的操作;因此,虽然您的进程可能没有更高优先级的线程在运行,但如果有其他线程在运行,您的仍然不会运行。

不过,这通常不是你需要担心的;默认优先级是“正常”优先级,在大多数情况下,您不应更改它。提高或降低它有很多含义。

【讨论】:

  • 所以那段代码实际上违背了线程的目的?因为目的是一次执行多个任务,而不必等待对方完成。最好不要使用它?
  • @YahooMania 不,在某些情况下这样做很重要。
  • @YahooMania 但是,除了线程示例之外,您不一定会遇到这种情况。这段代码的存在是为了帮助说明一个观点。
  • @AndrewBarber 在线程示例和实际线程代码之外,这肯定是阅读线程示例的全部重点。当然,在这种情况下这是人为的,但如果您等待太长时间以等待依赖于另一个线程的条件,则不解释放弃切片的重要性会破坏某人尝试学习线程的目的。
  • @AndrewBarber 在底部附近查看我的答案。
【解决方案2】:

如果同等优先级的线程准备好调度,Thread.Sleep(0) 将放弃线程的剩余时间片。

Thread.Sleep(1)(或任何其他值,但 1 是具有此效果的最低值)将无条件放弃线程的其余时间片。如果它想确保即使具有较低优先级的线程也有机会运行(并且这样的线程可能正在做一些阻塞该线程的事情,它必须这样做),那么它就是要去做的事情。

http://www.bluebytesoftware.com/blog/PermaLink,guid,1c013d42-c983-4102-9233-ca54b8f3d1a1.aspx 对此有更多了解。

【讨论】:

    【解决方案3】:

    如果主线程根本不休眠,那么其他线程将根本无法运行。

    插入 任意 长度的Sleep 允许其他线程一些 处理时间。使用较小的值(在这种情况下为 1 毫秒)意味着主线程似乎没有锁定。您可以使用 Sleep(0),但正如 Jon Hanna 指出的那样,这与 Sleep(1)(或实际上任何正值)具有不同的含义,因为它只允许运行具有相同优先级的线程。

    如果任务需要 5 秒,那么主线程将总共休眠 5,000 毫秒,但时间会更长。

    【讨论】:

    • 不完全正确。最小值为 0,但在这种情况下它不会让给低优先级的线程。
    【解决方案4】:

    这只是为了示例 - 他们希望确保工作线程有机会在主线程杀死它之前至少打印一次“工作线程:工作......”。

    正如 Andrew 所暗示的,这在示例中很重要,特别是因为如果您在单处理器机器上运行,主线程可能不会放弃处理器,甚至在后台线程有机会迭代一次之前就将其杀死。

    【讨论】:

      【解决方案5】:

      我今天注意到的有趣的事情。中断线程会引发ThreadInterruptedException。我试图捕捉异常,但由于某种原因不能。我的同事建议我将 Thread.Sleep(1) 放在 catch 语句之前,这样我就可以捕捉到 ThreadInterruptedException

              // Start the listener
              tcpListener_ = new TcpListener(ipAddress[0], int.Parse(portNumber_));
              tcpListener_.Start();
              try
              {
                  // Wait for client connection
                  while (true)
                  {
                      // Wait for the new connection from the client
                      if (tcpListener_.Pending())
                      {
                          socket_ = tcpListener_.AcceptSocket();
                          changeState(InstrumentState.Connected);
      
                          readSocket();
                      }
                      Thread.Sleep(1);
                  }
              }
      
              catch (ThreadInterruptedException) { }
      
              catch (Exception ex)
              {
                  MessageBox.Show(ex.Message, "Contineo", MessageBoxButtons.OK, MessageBoxIcon.Error);
                  Console.WriteLine(ex.StackTrace);
              }
      

      其他类...

              if (instrumentThread_ != null)
              {
                  instrumentThread_.Interrupt();
                  instrumentThread_ = null;
              }
      

      【讨论】:

      • 如果您取出 Pending() 测试并让 AcceptSocket()Start 之前阻止它也可能被捕获。原因是我的答案的延伸。线程不会有ThreadInterruptedException 被抛出,直到它阻塞或放弃它的时间片(不仅仅是到达它的量子结束并返回等待下一个量子)这是Thread.Sleep(1) 导致的,但是@ 987654331@ 没有。进入监视器或等待事件也会给它一个被抛出的机会。
      猜你喜欢
      • 1970-01-01
      • 2010-11-27
      • 2011-09-09
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-04
      相关资源
      最近更新 更多