Pergunta

Eu tenho um programa que foi construída em C ++ (MFC, Visual Studio 6.0) há vários anos e foi executado em uma determinada máquina Windows por algum tempo (mais de 5 anos). O PC foi substituído há um mês (o velho morreu), e desde então comportamento temporal do programa alterado. Eu preciso de ajuda para entender o porquê.

A principal funcionalidade do programa é para responder aos comandos das teclas enviando sinais ON e OFF para uma placa externa, com um atraso muito preciso entre o ON e OFF. Um fluxo exemplo de programa:

> wait for keystroke...
> ! keystroke occurred
> send ON message
> wait 150ms
> send OFF message

Diferentes combinações de teclas têm diferentes períodos de espera que lhes estão associados, entre 20ms e 150ms (um tempo muito determinista, dependendo da combinação de teclas específica). O tempo é muito importante. A espera é executado usando Sleep() simples. A precisão do sono no antigo PC foi 1-2ms desvio. Posso medir o tempo externamente ao computador (no cartão externo), assim que minha medição do tempo de sono é muito preciso. Por favor tenha em conta esta máquina executadas tais ciclos ON-sono-Off milhares de vezes por dia, durante anos, de modo que os dados de precisão que eu tenho é o som.

Uma vez que o PC foi substituído o desvio de tempo é mais do que 10ms.

Eu não instalar o PC anterior, por isso pode tinha alguns pacotes de software adicionais instalados. Além disso, eu tenho vergonha de admitir que eu não me lembro se o PC anterior era o Windows 2000 ou Windows XP. Tenho certeza de que era XP, mas não 100% (e eu não pode verificar agora ...). O novo é o Windows XP.

Eu tentei mudar o mecanismo de dormir para ser baseada em temporizadores, mas a precisão não melhorou.

Can nada explicar essa mudança? Existe um pacote de software que pode ter sido instalado no PC anterior que pode resolver o problema? Existe uma prática recomendada para lidar com o problema?

Foi útil?

Solução

A resolução de tempo no XP é de cerca de 10ms - o sistema basicamente "carrapatos" cada 10ms. O sono não é uma boa maneira de fazer timing exacto para essa razão. Tenho certeza win2000 tem a mesma resolução, mas se eu estiver errado, que poderia ser uma razão.

Você pode alterar essa resolução, pelo menos até 1ms - veja http: / /technet.microsoft.com/en-us/sysinternals/bb897569.aspx ou use este http: //www.lucashale.com/timerresolution/ -. há provavelmente uma chave de registro, bem como (Windows media player vai mudar isso temporizador, bem como, provavelmente, apenas enquanto ele está funcionando

Pode ser a resolução de alguma forma foi alterada em sua máquina de idade.

Outras dicas

Se a sua principal preocupação é a precisão, considere o uso spinlock . função Sleep() é uma dica para o programador para não re-agendar o fio dada por pelo menos x ms, não há nenhuma garantia de que o fio vai dormir exatamente durante o tempo especificado.

Normalmente Sleep () vai resultar em atraso de ~ 15 ms ou múltipla período de ~ 15ms dependendo do valor de sono. No das boas maneiras para descobrir haw ele funciona é o pseudo-código seguinte:

while true do
    print(GetTickCount());
    Sleep(1);
end;

E também vai mostrar que o comportamento desse código é diferente para, digamos, o Windows XP e Vista / Win 7

Como já foi mencionado, o sono tem uma precisão grosseira.

Eu normalmente uso boost :: asio para este tipo de tempo:

// Set up the io_service and deadline_timer
io_service io_
deadline_timer timer(io_service);

// Configure the wait period
timer.expires_from_now(posix_time::millisec(5));
timer.wait();

Asio usa a implementação mais eficaz para a sua plataforma; no Windows Eu acredito que usa sobrepostas IO.

Se eu definir o período de tempo de 1 ms e repetir o "temporizador". chama 10000 vezes a duração é tipicamente cerca de 10005-10100 ms. Muito preciso, código de plataforma cruzada (embora a precisão é diferente no Linux) e muito fácil de ler.

Eu não posso explicar por que seu PC anterior foi embora tão precisos; O sono tem sido +/- 10ms sempre que eu usei-o -. Pior se o PC está ocupado

É o seu novo PC multi-core e o antigo single-core? A diferença na precisão de temporização pode ser o uso de vários segmentos e mudança de contexto.

O sono é dependente do relógio do sistema. A sua nova máquina provavelmente tem um tempo diferente do que a sua máquina anterior. Do documentação :

Esta função faz com que um thread para abandonar o restante de seu tempo fatia e se tornar N� Execut�el para um Intervalo com base no valor de dwMilliseconds. O relógio do sistema "Ticks", a uma taxa constante. E se dwMilliseconds é menor que o resolução do relógio do sistema, o thread pode dormir por menos do que o período de tempo especificado. E se dwMilliseconds é maior do que um carrapato, mas menos de dois, a espera pode estar em qualquer lugar entre um e dois carrapatos, e assim por diante. Para aumentar a precisão de o intervalo de suspensão, ligue para o timeGetDevCaps funcionar para determinar a resolução do temporizador mínimo suportado e a função de timeBeginPeriod defina a resolução do temporizador à sua mínimo. Tenha cuidado ao chamar timeBeginPeriod, como freqüentes chamadas podem afetar significativamente o relógio do sistema, o consumo de energia do sistema e o programador. Se você chamar timeBeginPeriod, chamá-lo uma vez no início da aplicação e certifique-se de chamar o timeEndPeriod função no final do aplicação.

A documentação parece implicar que você pode tentar torná-lo mais preciso, mas eu não iria tentar que, se eu fosse você. Basta usar um temporizador.

O que temporizadores que você substituí-lo com? Se você usou SetTimer (), que temporizador suga também.
A solução correcta é usar a maior resolução TimerQueueTimer .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top