【发布时间】:2012-09-07 15:34:47
【问题描述】:
在我的 .NET 应用程序中,我必须重放一系列传感器事件。所以我创建了一个线程来触发这些事件(通常大约每 1-4 毫秒)。我在这个线程中实现了一个循环,并使用Thread.Sleep(...) 让线程在事件之间休眠。
基本上是这样的:
void RunThread() {
var iter = GetAllEvents().GetEnumerator();
if (!iter.MoveNext()) {
return;
}
DateTime lastEventTime = iter.Current.Timestamp;
FireEvent(iter.Current);
while (iter.MoveNext()) {
MyEvent nextEvent = iter.Current;
int timeout = (int)(nextEvent.Timestamp - lastEventTime).TotalMilliseconds;
Thread.Sleep(timeout);
FireEvent(nextEvent);
lastEventTime = nextEvent.Timestamp;
}
}
现在,我的问题是 Thread.Sleep() 有时会遵守指定的超时时间,有时则不会。
我添加了一个检查(使用StopWatch,在上面的代码中不可见)关于睡眠实际花费了多长时间。以下是一些结果:
Expected timeout of 1 ms but got 15 ms.
Expected timeout of 2 ms but got 13 ms.
Expected timeout of 3 ms but got 15 ms.
Expected timeout of 2 ms but got 13 ms.
Expected timeout of 1 ms but got 13 ms.
Expected timeout of 1 ms but got 15 ms.
Expected timeout of 2 ms but got 13 ms.
Expected timeout of 2 ms but got 40 ms.
为什么Thread.Sleep() 表现得那样“随机”?
注意事项:
- 该线程运行时,Window 任务管理器不显示任何 cpu 使用情况。
- 行为随机变化,但至少会持续几秒钟。例如,有一次我启动线程时,它运行良好。下一次它一直运行缓慢。下一次它快速运行几秒钟,然后减速或相反。
更新:下面是一些伪代码,显示了Sleep 的行为方式:
bool ChooseRespectTimeout() {
if (this.notYetChosen) {
this.respectTimeout = ChooseRandomly()
this.notYetChosen = false
reset this.notYetChosen after random time period
}
return this.respectTimeout
}
void Sleep(int timeout) {
if (ChooseRespectTimeout())
Thread.Sleep(timeout)
else
Thread.Sleep(timeout * 10)
}
【问题讨论】:
-
我不知道他们为什么没有更新该方法的文档。该方法实际上只是调用 Sleep msdn.microsoft.com/en-us/library/windows/desktop/… 详细说明缺乏准确性。
-
Thread.Sleep真正做的是放弃控制 大约 指定的毫秒。那可能或多或少。操作系统交还控制权的速率由系统时间片决定,即 10-15 毫秒。所以,实际上Thread.Sleep只能精确到最近的量子。但是,正如其他人指出的那样,如果 CPU 负载过重,则时间会更长。此外,如果您的线程的优先级低于所有其他线程,则可能无法获得时间。 -
长话短说,只使用
Thread.Sleep让其他应用程序/线程有一个时间片,并且只使用 Thread.Sleep(1) 来做到这一点。 bit.ly/IhxHSk 即不要使用Thread.Sleep进行计时。 -
我已经改变了我的实现。我仍然很好奇它为什么会这样。就像我在问题中所说的那样,没有明显的 CPU 负载(所以这不是问题)。此外,线程具有最高优先级,仍然表现出这种奇怪的行为。
-
顺便说一句,这不是现在
Sleep的行为。Sleep选择在时间到期(或接近)后不交还控制权。它不能选择不“尊重”超时当Sleep被调用。
标签: .net multithreading