.NET Thread.Sleep () jest losowo nieprecyzyjny

W mojej aplikacji .NET muszę powtórzyć serię zdarzeń czujnika. Stworzyłem więc wątek, który uruchamia te zdarzenia (zwykle około 1 - 4 milisekundy). Zaimplementowałem pętlę w tym wątku i użyłemThread.Sleep(...) wstawić wątek w stan uśpienia między zdarzeniami.

Zasadniczo wygląda to tak:

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;
  }
}

Teraz mam problemThread.Sleep() czasami szanuje określony limit czasu, a czasami nie.

Dodałem czek (używającStopWatch, niewidoczny w powyższym kodzie) na temat czasu trwania snu. Oto kilka wyników:

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.

DlaczegoThread.Sleep() zachowywać się tak „losowo”?

Uwagi:

Menedżer zadań Window nie pokazuje użycia procesora podczas działania tego wątku.Zachowanie zmienia się losowo, ale utrzymuje się przez co najmniej kilka sekund. Na przykład, gdy raz uruchomię wątek, działa dobrze. Następnym razem działa powoli. Następnym razem będzie działać szybko przez kilka sekund, niż spowalnia lub odwrotnie.

Aktualizacja: Oto pseudokod, który pokazuje, jakSleep zachowuje się:

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)
}

questionAnswers(7)

yourAnswerToTheQuestion