.NET Thread.Sleep () является случайным неточным
В моем приложении .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()
веди себя так "случайным образом"?
Заметки:
Диспетчер задач Windows не работаетне показывать использование процессора во время работы этого потока.Поведение меняется случайным образом, но сохраняется как минимум пару секунд. Например, один раз, когда я запускаю поток, он работает нормально. В следующий раз все работает медленно. В следующий раз он будет работать быстро в течение нескольких секунд, а затем замедлится или наоборот.Обновить: Вот'Какой-то псевдокод, который показывает, как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)
}