【问题标题】:How do I get my C# program to sleep for 50 msec?如何让我的 C# 程序休眠 50 毫秒?
【发布时间】:2010-09-10 14:30:59
【问题描述】:

如何让我的 C# 程序休眠 50 毫秒?

这似乎是一个简单的问题,但我有一个暂时的脑力衰竭时刻!

【问题讨论】:

  • 重新标记为 VB.NET,因为那里的答案也有效。
  • 没有 DrFloyd5, ;不适用于 VB.NET,对吧?
  • 如果我在 VB.Net 团队,我会添加 ;作为下一版本语言的注释字符...
  • 我认为 VB 程序员足够聪明,可以找出等价物。
  • 好吧,只是为了确保,现在他们不必这样做了。

标签: c# vb.net


【解决方案1】:

从 .NET Framework 4.5 开始,您可以使用:

using System.Threading.Tasks;

Task.Delay(50).Wait();   // wait 50ms

【讨论】:

【解决方案2】:

您无法在 Windows 中指定准确的睡眠时间。为此,您需要一个实时操作系统。您能做的最好的事情就是指定一个最小睡眠时间。然后由调度程序来唤醒你的线程。并且从不在 GUI 线程上调用 .Sleep()

【讨论】:

    【解决方案3】:

    两全其美:

    using System.Runtime.InteropServices;
    
        [DllImport("winmm.dll", EntryPoint = "timeBeginPeriod", SetLastError = true)]
        private static extern uint TimeBeginPeriod(uint uMilliseconds);
    
        [DllImport("winmm.dll", EntryPoint = "timeEndPeriod", SetLastError = true)]
        private static extern uint TimeEndPeriod(uint uMilliseconds);
        /**
         * Extremely accurate sleep is needed here to maintain performance so system resolution time is increased
         */
        private void accurateSleep(int milliseconds)
        {
            //Increase timer resolution from 20 miliseconds to 1 milisecond
            TimeBeginPeriod(1);
            Stopwatch stopwatch = new Stopwatch();//Makes use of QueryPerformanceCounter WIN32 API
            stopwatch.Start();
    
            while (stopwatch.ElapsedMilliseconds < milliseconds)
            {
                //So we don't burn cpu cycles
                if ((milliseconds - stopwatch.ElapsedMilliseconds) > 20)
                {
                    Thread.Sleep(5);
                }
                else
                {
                    Thread.Sleep(1);
                }
            }
    
            stopwatch.Stop();
            //Set it back to normal.
            TimeEndPeriod(1);
        }
    

    【讨论】:

      【解决方案4】:
      System.Threading.Thread.Sleep(50);
      

      但请记住,在主 GUI 线程中执行此操作会阻止您的 GUI 更新(它会感觉“缓慢”)

      只需删除 ; 即可使其也适用于 VB.net。

      【讨论】:

      • 方法中调用sleep后,程序是否会继续在后台执行(不创建新线程)?另外,如果我在一个新线程中调用 sleep,主线程会继续工作吗?
      • @JayNirgudkar 调用 Sleep 的线程将被停止。其他线程不受影响。
      • 不保证准确。
      【解决方案5】:

      为了可读性:

      using System.Threading;
      Thread.Sleep(TimeSpan.FromMilliseconds(50));
      

      【讨论】:

        【解决方案6】:

        既然现在你有 async/await 功能,睡眠 50 毫秒的最佳方法是使用 Task.Delay:

        async void foo()
        {
            // something
            await Task.Delay(50);
        }
        

        或者,如果您的目标是 .NET 4(使用 Async CTP 3 for VS2010 或 Microsoft.Bcl.Async),您必须使用:

        async void foo()
        {
            // something
            await TaskEx.Delay(50);
        }
        

        这样你就不会阻塞 UI 线程。

        【讨论】:

        • 你能在这个延迟期间response.flush,如果它在一个循环中?
        • 不,你不能。我相信有一个FlushAsync 版本。
        • 另一种不需要async 声明的方法是调用Task.Delay(50).Wait();
        【解决方案7】:

        在(几乎)任何编程语言中,基本上都有 3 种等待选择:

        1. 松散的等待
          • 在给定时间内执行线程块(= 不消耗处理能力)
          • 阻塞/等待线程无法处理
          • 不太精确
        2. 紧等待(也称为紧循环)
          • 处理器在整个等待时间间隔内都非常繁忙(实际上,它通常会消耗一个内核 100% 的处理时间)
          • 在等待时可以执行一些操作
          • 非常精确
        3. 前 2 个的组合
          • 它通常结合了 1. 的处理效率和 2. 的严谨性 + 做某事的能力。

        for 1. - C# 中的松散等待:

        Thread.Sleep(numberOfMilliseconds);
        

        但是,Windows 线程调度程序导致 Sleep() 的准确度约为 15 毫秒(因此即使计划仅等待 1 毫秒,睡眠也可以轻松等待 20 毫秒)。

        对于 2. - C# 中的紧张等待是:

        Stopwatch stopwatch = Stopwatch.StartNew();
        while (true)
        {
            //some other processing to do possible
            if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
            {
                break;
            }
        }
        

        我们也可以使用DateTime.Now 或其他时间测量方式,但Stopwatch 更快(这在紧密循环中确实会变得可见)。

        3. - 组合:

        Stopwatch stopwatch = Stopwatch.StartNew();
        while (true)
        {
            //some other processing to do STILL POSSIBLE
            if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
            {
                break;
            }
            Thread.Sleep(1); //so processor can rest for a while
        }
        

        此代码定期将线程阻塞 1 毫秒(或稍长,取决于操作系统线程调度),因此处理器在阻塞时间并不忙,代码不会消耗 100% 的处理器功率。仍然可以在阻塞之间执行其他处理(例如:更新 UI、处理事件或进行交互/通信)。

        【讨论】:

        • Timer 也可能感兴趣
        【解决方案8】:
        Thread.Sleep(50);
        

        操作系统不会在指定的时间内安排线程执行。此方法将线程的状态更改为包含 WaitSleepJoin。

        此方法不执行标准 COM 和 SendMessage 泵送。 如果您需要在具有 STAThreadAttribute 的线程上休眠,但您想要执行标准 COM 和 SendMessage 泵送,请考虑使用指定超时间隔的 Join 方法的重载之一。

        Thread.Join
        

        【讨论】:

          【解决方案9】:

          使用此代码

          using System.Threading;
          // ...
          Thread.Sleep(50);
          

          【讨论】:

            猜你喜欢
            • 2010-09-27
            • 2021-11-20
            • 2021-06-21
            • 2019-03-07
            • 2011-05-10
            • 1970-01-01
            • 2011-08-13
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多