如何使C#程序睡眠50毫秒?


272

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

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


1
重新标记为VB.NET,因为答案也在那里起作用。
DrFloyd09年

没有DrFloyd5 ,;在VB.NET上不起作用,对吧?
Zanoni

16
如果我是VB.Net团队的成员,我会添加;作为下一版语言的注释字符...
Joel Coehoorn

4
我认为VB程序员是足够明亮找出相当于..
BlueRaja -丹尼Pflughoeft

好吧,只是为了确保,现在他们不必这样做了。
PsychoData'2

Answers:


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

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

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


在使用方法调用sleep之后,程序是否将继续在后台执行(不创建新线程)?另外,如果我在新线程中调用sleep,主线程会继续工作吗?
Jay Nirgudkar 2015年

@JayNirgudkar调用睡眠的线程将停止。其他线程不受影响。
Isak Savo 2015年

这不能保证是准确的。
Akumaburn

150

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

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

1。-在C#中等待松散:

Thread.Sleep(numberOfMilliseconds);

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

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


1
计时器可能也很有趣
JonnyRaa 2015年

55

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


44

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

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

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

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

这样,您将不会阻止UI线程。


如果延迟,您是否可以在此延迟期间进行response.flush?
Teoman shipahi 2013年

你不能。我相信有一个FlushAsync版本。
Toni Petrina 2013年

6
不需要async声明的替代方法是致电Task.Delay(50).Wait();
stuartd


14
Thread.Sleep(50);

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

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

Thread.Join

5

为了提高可读性:

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

0

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

using System.Threading.Tasks;

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

-1

两全其美:

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);
    }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.