【问题标题】:C# Thread.Sleep(1000) takes much more than 1000ms on some pcC# Thread.Sleep(1000) 在某些电脑上花费的时间超过 1000 毫秒
【发布时间】:2015-03-30 17:10:33
【问题描述】:

我编写了一个 c# 程序来倒计时 5 秒。我要做的是:

        new Task(() =>
        {

                try
                {
                        this.Invoke((Action)delegate()
                        {
                            label1.Text = "5"; // 4, 3, 2..etc
                        });
                    }
                    Thread.Sleep(1000);
                }
                catch
                {
                    // form could be disposed
                    break;
                }

            }

        }).Start();

这适用于我的 PC,但是,当我将程序复制到窗口平板电脑时,Thread.Sleep(1000) 提供了超过 1 秒的时间。也就是说,从 5,4,3,2,1 更新标签需要超过 5 秒(实际上超过 10 秒)。或者,更新label1.Text =“5”等需要太长时间?这对我来说没有意义。我想知道有什么问题吗?

【问题讨论】:

  • 没有错。 Thread.Sleep(n) 保证,您的线程不会在 n 毫秒过去之前被通知/唤醒,仅此而已。您的线程 bean 是否在 n 毫秒过去之前被唤醒?没有。Thread.Sleep(n) 工作得很好。

标签: c# multithreading timer sleep


【解决方案1】:

Sleep 将在再次激活线程之前等待至少那么长时间,但它总是可以比这更长。一秒钟后,线程变为有资格由 CPU 调度程序执行,并且调度程序能够随时运行它。如果它特别忙,和/或正在使用不专注于快速允许新活动线程运行的调度算法,则可能需要一些时间。

【讨论】:

    【解决方案2】:

    Servy 的回答是正确的。更多详情,请阅读文档:

    https://msdn.microsoft.com/en-us/library/windows/desktop/ms686298.aspx

    其中规定:

    请注意,不保证就绪线程会立即运行。因此,线程可能要等到休眠间隔过去一段时间后才会运行。有关详细信息,请参阅调度优先级。

    优先文档在这里:

    https://msdn.microsoft.com/en-us/library/windows/desktop/ms685100.aspx

    不过更笼统地说:你做错了什么。永远不要像这样使用Sleep。如果您想等待一段时间,请使用 计时器 或使用 Delay 任务。永远不要在测试代码之外休眠这样的线程。编写代码的正确方法可能类似于

    for (int countdown = 5; countdown > 0; countdown -= 1)
    {
        label1.Text = countdown.ToString();
        await Task.Delay(1000);
    }
    

    或者,创建一个有计时器和计数器的类,启动计时器以每秒计时几次,将当前时间与上次更新标签的时间进行比较,如果超过一秒,更新标签。

    【讨论】:

    • 当然,CPU 调度算法将依赖于操作系统,而不是对所有 C# 程序都是统一的。在 Unix 操作系统中的 Mono 上运行的 C# 代码将具有不同的调度特征。
    • 当您说“永远不要在测试代码之外让这样的线程休眠”时,您是建议将所有 Thread.Sleep 实例替换为 Delay 任务,还是仅适用于界面上下文?
    • @nintendojunkie: Sleep 不是方法设计的一个很好的例子。它有特殊用途的箱子;例如,Sleep(0)Sleep(1) 的含义非常不同。它被记录为不提供实际睡眠时间的保证;它可以比给定的参数睡更多或更少的时间。它不泵送消息,因此它会在应用程序中引入挂起。它完全浪费了一个线程,一个昂贵的资源。它几乎从来没有被正确使用过,除非你有真正令人信服的理由来使用它,否则真的应该避免使用它。
    • 有趣。我可能会就此发布一个后续问题。
    猜你喜欢
    • 2012-07-07
    • 1970-01-01
    • 2021-06-19
    • 1970-01-01
    • 2021-07-29
    • 2023-03-09
    • 1970-01-01
    • 2013-08-11
    • 2013-01-01
    相关资源
    最近更新 更多