Thread.Sleep () é aleatoriamente impreciso.

No meu aplicativo .NET, tenho que reproduzir uma série de eventos de sensor. Então eu criei um thread que dispara esses eventos (geralmente a cada 1 - 4 milissegundos). Eu implementei um loop neste thread e useiThread.Sleep(...) para colocar o segmento para dormir entre os eventos.

Basicamente parece assim:

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

Agora, meu problema é queThread.Sleep() às vezes respeita o tempo limite especificado e às vezes não.

Eu adicionei um cheque (usandoStopWatch, não visível no código acima) quanto tempo durou o sono. Aqui estão alguns resultados:

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.

PorqueThread.Sleep() se comportar como "aleatoriamente"?

Notas:

O gerenciador de tarefas do Windows não mostra nenhum uso de CPU enquanto esse segmento é executado.O comportamento muda aleatoriamente, mas persiste por pelo menos alguns segundos. Por exemplo, uma vez quando eu inicio o segmento, ele é executado corretamente. A próxima vez que correr devagar o tempo todo. A próxima vez que correr rápido por alguns segundos, é mais lento ou vice-versa.

Atualizar: Aqui está um pseudo-código que mostra comoSleep comporta-se:

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