关于vb.net:如何让我的C#程序睡眠50毫秒?

关于vb.net:如何让我的C#程序睡眠50毫秒?

How do I get my C# program to sleep for 50 msec?

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

这似乎是一个简单的问题,但是我正处于暂时性的脑衰竭时刻!


1
System.Threading.Thread.Sleep(50);

但是请记住,在主GUI线程中执行此操作将阻止您的GUI更新(感觉"缓慢")。

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


(几乎)任何编程语言都有3种选择可以等待:

  • 宽松的等待

    • 在给定的时间执行线程块(=不消耗处理能力)
    • 无法在阻塞/等待的线程上进行处理
    • 不太精确
  • 紧等待(也称为紧循环)

    • 处理器在整个等待时间间隔内非常繁忙(实际上,它通常消耗一个内核的处理时间的100%)
    • 等待时可以执行一些动作
    • 非常精确
  • 前2个的组合

    • 它通常结合了1.的处理效率和2的精度+做某事的能力。
  • 1。-在C#中等待松散:

    1
    Thread.Sleep(numberOfMilliseconds);

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    Stopwatch stopwatch = Stopwatch.StartNew();
    while (true)
    {
        //some other processing to do possible
        if (stopwatch.ElapsedMilliseconds >= millisecondsToWait)
        {
            break;
        }
    }

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

    3。-组合:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    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毫秒(或稍长一些,具体取决于OS线程调度),因此处理器在阻塞时间并不忙,并且代码不会消耗100%的处理器功率。在阻塞之间仍然可以执行其他处理(例如:UI更新,事件处理或进行交互/通信工作)。


    您无法在Windows中指定确切的睡眠时间。为此,您需要一个实时操作系统。您能做的最好的就是指定最短的睡眠时间。然后由调度程序在那之后唤醒您的线程。永远不要在GUI线程上调用.Sleep()


    从现在开始,您具有异步/等待功能,最好的睡眠时间为50ms是使用Task.Delay:

    1
    2
    3
    4
    5
    async void foo()
    {
        // something
        await Task.Delay(50);
    }

    或者,如果您以.NET 4(针对VS2010的Async CTP 3或Microsoft.Bcl.Async)为目标,则必须使用:

    1
    2
    3
    4
    5
    async void foo()
    {
        // something
        await TaskEx.Delay(50);
    }

    这样,您就不会阻塞UI线程。


    使用此代码

    1
    2
    3
    using System.Threading;
    // ...
    Thread.Sleep(50);

    1
    Thread.Sleep(50);

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

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

    1
    Thread.Join


    1
    Thread.Sleep

    为了提高可读性:

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

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

    1
    2
    3
    using System.Threading.Tasks;

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

    两全其美:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    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);
        }


    推荐阅读