我想在1毫秒内调用线程休眠。我读到thread.Sleep
和Windows操作系统都不支持这一点。
有什么解决办法呢?
对于所有想知道我为什么需要这个的人:我正在做一个压力测试,想知道我的模块每秒能处理多少条消息,所以我的代码是:
// 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);
}
我很乐意听听你对那件事的意见。
6条答案
按热度按时间xmd2e60i1#
一个sleep调用通常会阻塞超过1毫秒的时间(这取决于操作系统和系统,但根据我的经验,
Thread.Sleep(1)
的阻塞时间通常在12- 15 ms之间)。Windows通常不是作为real-time operating system设计的。这种类型的控制通常不可能在普通(桌面/服务器)版本的Windows上实现。
你能得到的最接近的方法通常是旋转和消耗CPU周期,直到你达到你想要的等待时间(用高性能计数器测量)。然而,这是相当可怕的-你会消耗掉整个CPU,即使这样,你可能会得到操作系统的preempted有时和有效的“睡眠”超过1 ms...
xsuvu9jc2#
下面的代码肯定会提供一种更精确的阻塞方式,而不是调用
Thread.Sleep(x);
(尽管这个方法会 * 阻塞 * 线程,而不是让它进入 * 睡眠 *)。下面我们使用StopWatch
类来测量我们需要保持循环和阻塞调用线程多长时间。示例用法,
smdnsysy3#
"为什么"
通常,一台机器上的CPU和内核数量非常有限--如果是独立的执行单元,则数量很少。
另一方面,有许多进程和更多的线程。每个线程需要一些处理器时间,这是由Windows核心进程内部分配的。通常Windows阻止所有线程,并给特定线程一定量的CPU核心时间,然后将上下文切换到其他线程。
当你调用Thread.Sleep时,不管你把Windows给线程的整个时间间隔杀得多短,因为没有理由简单地等待它,上下文会立即切换。当Windows下次给你的线程一些CPU时,它可能需要几毫秒。
使用什么?
或者,您可以使用spin your CPU,spinning,这不是一件糟糕的事情,它可能非常有用。例如,它在 System.Collections.Concurrent 命名空间中使用了很多非阻塞集合,例如:
zwghvu4y4#
使用
Thread.Sleep(1)
或Thread.Sleep(0)
的大多数合理原因都涉及到相当高级的线程同步技术。就像Reed说的,使用常规技术不会得到所需的分辨率。我不确定你想要完成的是什么,但是我想我可以假设你想让一个动作以1毫秒的间隔发生。如果是这样的话,那么看看multimedia timers。它们可以提供低至1ms的分辨率。不幸的是,.NET框架中没有内置的API(据我所知)可以利用这个Windows特性。但是你可以使用互操作层直接调用Win32 API。甚至有用C#做这件事的例子。2fjabf4q5#
在过去的好日子里,当需要亚毫秒分辨率时,您会使用Win32的“QueryPerformanceTimer”API。
似乎有更多关于这个主题的信息在代码项目:http://www.codeproject.com/KB/cs/highperformancetimercshar.aspx
这将不允许您以ReedCopsey指出的相同分辨率“Sleep()”。
**编辑:**正如Reed Copsey和Brian Gideon所指出的,QueryPerformanceTimer在.NET中已被
Stopwatch
所取代eni9jsuy6#
我在寻找和OP一样的东西,并且设法找到了一个适合我的答案。我很惊讶其他的答案都没有提到这一点。
调用Thread.Sleep()时,可以使用以下两种重载之一:一个以毫秒数表示的int值,或一个TimeSpan值。
TimeSpan的构造函数有很多重载。其中一个是一个long,表示TimeSpan所代表的tick数。一个tick比1ms短很多。事实上,TimeSpan文档的另一部分给出了10000个tick在1ms内发生的例子。
因此,我认为这个问题最接近的答案是,如果您希望Thread.Sleep的时间少于1ms,那么您应该创建一个时间间隔少于1ms的TimeSpan,然后将其传递给Thread.Sleep()。