Thread.Sleep小于1毫秒

Ere*_*rez 28 .net c# multithreading

我想用不到1毫秒的时间调用线程休眠.我读到没有thread.Sleep也没有Windows-OS支持.

那是什么解决方案?

对于所有想知道我为什么需要这个的人:我正在进行压力测试,并想知道我的模块每秒可以处理多少消息.所以我的代码是:

 // Set the relative part of Second hat will be allocated for each message 
 //For example: 5 messages - every message will get 200 miliseconds 
 var quantum = 1000 / numOfMessages;

 for (var i = 0; i < numOfMessages; i++)
 {
      _bus.Publish(new MyMessage());
      if (rate != 0) 
          Thread.Sleep(quantum);
 }
Run Code Online (Sandbox Code Playgroud)

我很高兴得到你的意见.

Ree*_*sey 42

你不能这样做.单个睡眠调用通常会阻塞远超过一毫秒(它依赖于操作系统和系统,但根据我的经验,它Thread.Sleep(1)往往会阻塞在12-15ms之间).

通常,Windows不是作为实时操作系统设计的.在普通(桌面/服务器)版本的Windows上,通常无法实现此类控制.

你可以得到的最接近的是旋转和吃CPU周期,直到你达到你想要的等待时间(用高性能计数器测量).然而,这非常糟糕 - 你将占用整个CPU,即便如此,你很可能会被操作系统抢占,并且有效地"睡眠"时间超过1毫秒......

  • 对于其他人来到这个线程,我测试了使用Thread.Sleep(1)在linux/ubuntu下使用Mono C#进行验证,它正好睡眠了1ms. (7认同)
  • Vista和更新的支持无时间安排.如果硬件支持这一点,内核可以安排在1ms以下,但睡眠限制为1ms.请记住,睡眠只能保证至少在这段时间内休眠,但不能保证线程会被唤醒. (2认同)
  • 我讨厌这个答案。就睡眠而言,这在技术上是正确的,但就 OP 和大多数人想要的而言,下面的 Sam 提供了一个蛮力但非常有效的解决方案。这个答案的高票数和坚定的“你不能这样做”阻止人们向下滚动并找到他们的解决方案。 (2认同)

Sam*_*Sam 20

下面的代码肯定会提供一种更精确的阻塞方式,而不是调用Thread.Sleep(x);(尽管这种方法会阻塞线程,而不是让它进入休眠状态).下面我们使用StopWatch类来测量我们需要多长时间保持循环并阻塞调用线程.

using System.Diagnostics;

private static void NOP(double durationSeconds)
{
    var durationTicks = Math.Round(durationSeconds * Stopwatch.Frequency);
    var sw = Stopwatch.StartNew();

    while (sw.ElapsedTicks < durationTicks)
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

用法示例,

private static void Main()
{
    NOP(5); // Wait 5 seconds.

    Console.WriteLine("Hello World!");

    Console.ReadLine();
}
Run Code Online (Sandbox Code Playgroud)

  • 问题是明确询问如何***睡眠***不到1毫秒.这个答案将***阻止***而不是睡觉.因为这个问题是关于压力测试的,所以在这种情况下它可能已经足够好了,所以无论如何都要进行投票. (2认同)
  • @Saryk 根据 [this](/sf/answers/405568061/) 帖子,滴答的持续时间取决于操作系统/硬件。但是,您可以使用`秒表`的[`频率`](https://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.frequency(v=vs.110).aspx)属性来确定机器上刻度的确切长度。 (2认同)

ole*_*sii 10

为什么?
通常,一台机器上的CPU和核心数量非常有限 - 如果是独立的执行单元,您只能得到一小部分.

另一方面,有许多进程和更多线程.每个线程都需要一些处理器时间,这是由Windows核心进程在内部分配的.通常,Windows会阻塞所有线程并为特定线程提供一定量的CPU核心时间,然后将上下文切换到其他线程.

当你调用Thread.Sleep无论你杀掉Windows给线程的整个时间跨度有多小,因为没有理由等待它直接切换上下文.当Windows下次为您的线程提供一些CPU时,可能需要几毫秒.

用什么?
或者,您可以旋转您的CPU,旋转并不是一件可怕的事情,并且非常有用.例如,它在System.Collections.Concurrent命名空间中使用很多非阻塞集合,例如:

SpinWait sw = new SpinWait();
sw.SpinOnce();
Run Code Online (Sandbox Code Playgroud)


Bri*_*eon 6

使用Thread.Sleep(1)Thread.Sleep(0)涉及相当高级的线程同步技术的大多数合理原因.像里德说的那样,你不会使用传统技术获得所需的分辨率.我不确定你想要完成什么,但我想我可以假设你想要以1毫秒的间隔发生一次动作.如果是这种情况,那么看看多媒体计时器.它们可以提供低至1毫秒的分辨率.不幸的是,.NET Framework中没有内置的API(我知道)可以使用这个Windows功能.但是您可以使用互操作层直接调用Win32 API.甚至在C#中也有这样做的例子.


S.C*_*sen 5

在过去,当需要亚毫秒级分辨率时,您会使用 Win32 的“QueryPerformanceTimer”API。

Code-Project 上似乎有更多关于该主题的信息:http : //www.codeproject.com/KB/cs/highperformancetimercshar.aspx

这将不允许您以 Reed Copsey 指出的相同分辨率“Sleep()”。

编辑: 正如 Reed Copsey 和 Brian Gideon 所指出的,QueryPerfomanceTimer 已被Stopwatch.NET取代

  • 这不会阻止 - 它只是为您提供了一种测量方法。`Stopwatch` 类在 C# 中有效地做到了这一点(通过在内部使用 `QueryPerformanceCounter`)。 (2认同)