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