Obter tempo em milissegundos usando C #

131

Estou criando um programa no qual preciso passar o tempo em milissegundos. Com o tempo, quero dizer um número que nunca é igual a si mesmo e é sempre 1000 números maior do que era um segundo atrás. Eu tentei converter DateTime.Nowpara um TimeSpane tirar TotalMillisecondsproveito disso ... mas ouvi dizer que não é perfeitamente preciso.

Existe uma maneira mais fácil de fazer isso?

Entidade
fonte
Você espera que duas chamadas sempre conduzam valores crescentes? Em geral, as chamadas mais próximas do que o intervalo mínimo permitido pela resolução do timer renderão o mesmo valor. Você precisaria adicionar seu próprio desempatador na forma de um serializador de precisão falsa.
Steven Sudit 25/10/10
16
"Um número que nunca é igual a si mesmo". Isso parece ... complicado. ;)
Mizipzor 17/08/2012
1
NaN se encaixaria nesse requisito, na verdade. Apesar de "não ser um número", é um tipo de número e não é igual a si próprio.
precisa saber é

Respostas:

78

Use a Stopwatchclasse.

Fornece um conjunto de métodos e propriedades que você pode usar para medir com precisão o tempo decorrido.

Há algumas boas informações sobre como implementá-lo aqui:

Testes de desempenho: medições precisas de tempo de execução com System.Diagnostics.Stopwatch

RedFilter
fonte
8
O cronômetro faz parte do Diagnóstico. Deve ser usado em código real?
Andrey
Normalmente, isso é preciso apenas nos 15ms mais próximos.
Steven Sudit 25/10/10
11
quão caro é embora? talvez devêssemos cronômetro um cronômetro :)
jb.
3
@ Steven, isso depende do sistema operacional e do hardware subjacente. Se disponível, é usado um timer de alta resolução, que é o caso de todas as versões atuais do Windows x86 baseadas em desktop e servidor que eu conheço. Verifique as propriedades Frequency e IsHighResolution para obter mais detalhes. No nível do sistema operacional, QueryPerformanceCounter e QueryPerformanceFrequency são as APIs de baixo nível que apóiam essa funcionalidade.
Chris Taylor
320
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;

É assim que os vários métodos de conversão Unix são implementados na DateTimeOffsetclasse (.NET Framework 4.6+, .NET Standard 1.3+):

long milliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
Evan Mulawski
fonte
65
O título é "obter tempo em milissegundos". Esta resposta é útil.
Aerospace
33
Sim, para aqueles que procuram uma resposta para a pergunta apresentada, isso foi muito útil, obrigado.
user430788
1
Se você deseja decimais (mesmo que DateTime.Nownão seja "atualizado" com muita frequência), é claro que use decimal milliseconds = DateTime.Now.Ticks / (decimal)TimeSpan.TicksPerMillisecond;.
Jeppe Stig Nielsen
1
Isso é muito mais útil do que a resposta selecionada para os resultados da pesquisa e até para o que recolho da pergunta original.
bwoogie
1
Essa resposta salvou minha vida. Tem código semelhante, mas não funciona. Não foi possível descobrir o porquê. Então vi o longtipo de dados na frente de milissegundos. Usando intcertamente vai transbordar.
FisNaN 28/03
13

A DateTime.Tickspropriedade obtém o número de ticks que representam a data e a hora.

10,000 Ticks é um milissegundo (10.000.000 ticks por segundo).

Itay Karo
fonte
4
Mas a resolução de carrapatos é muito menos do que 1 / 10000s, talvez 1 / 62s
codymanix
2
@codymanix - do MSDN:A single tick represents one hundred nanoseconds or one ten-millionth of a second. There are 10,000 ticks in a millisecond.
Itay Karo
5
Claro que sim, mas o sistema operacional não tem a resolução exata.
Codymanix 25/10/10
6
@codymanix está correto. Por analogia, um Angstrom é uma unidade de comprimento; dez bilhões de Angstroms fazem um metro. Você pode escrever uma função que relate sua altura como um número inteiro de 64 bits em Angstroms, mas se tudo o que você tem é uma passagem de metrô precisa do centímetro, o fato de a função representar uma precisão subanométrica é completamente irrelevante. Os dígitos menos significativos serão lixo.
Eric Lippert
4
@ RedFilter: Se você realmente soubesse sua idade no milissegundo mais próximo, poderia dizer algo como "Quando eu piscar novamente, minha idade será x milissegundos". O problema mais profundo não é a comunicação, mas a medição: é improvável que seu nascimento seja conhecido até no segundo mais próximo.
Steven Sudit 25/10/10
11

Eu uso a seguinte classe. Encontrei-o na Internet uma vez, postulado como o melhor NOW () .

/// <summary>Class to get current timestamp with enough precision</summary>
static class CurrentMillis
{
    private static readonly DateTime Jan1St1970 = new DateTime (1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    /// <summary>Get extra long current timestamp</summary>
    public static long Millis { get { return (long)((DateTime.UtcNow - Jan1St1970).TotalMilliseconds); } }
}

Fonte desconhecida.

schmijos
fonte
5
O FWIW, todo o objetivo desse trecho usado com frequência, é criar um registro de data e hora compatível com o padrão de registro de data e hora do Unix. Para isso, é vital. Se alguém quer apenas cronometrar, é desnecessariamente caro.
Página
8

Você pode tentar o QueryPerformanceCountermétodo nativo. Consulte http://www.pinvoke.net/default.aspx/kernel32/QueryPerformanceCounter.html para obter mais informações. É isso que a Stopwatchclasse usa.

Consulte Como obter o registro de data e hora da precisão de ticks no .NET / C #? Para maiores informações.

Stopwatch.GetTimestamp() dá acesso a este método:

public static long GetTimestamp() {
     if(IsHighResolution) {
         long timestamp = 0;
         SafeNativeMethods.QueryPerformanceCounter(out timestamp);
         return timestamp;
     }
     else {
         return DateTime.UtcNow.Ticks;
     }
 }
Pieter van Ginkel
fonte
1
O AFAIK StopWatch usa QueryPerformanceCounter internamente, se disponível
codymanix 25/10/10
Sim, a implementação interna de Stopwatch.GetTimestamp()realmente fornece acesso a esse método.
Pieter van Ginkel
5

Eu usei DateTime.Now.TimeOfDay.TotalMilliseconds (para o dia atual), espero que ajude você também.

Sarvan
fonte
1
que não retornará valores crescentes (conforme exigido pelo pôster original), pois o TimeOfDay é redefinido para zero todos os dias à meia-noite. Além disso, ele teria os mesmos problemas potenciais que o pôster mencionou ao usar o DateTime. Agora, é possível obter o total de milissegundos a partir disso.
Jim O'Neil
3
Jim O'Neil Eu concordo com você, é por isso que mencionei "(para o dia atual)" no meu post ... Btw, minha solução funcionou para o meu problema, pois meu problema não é específico da data, eu simplesmente precisava a parte de milissegundos para ser usada como contador, então eu a publiquei aqui. Eu sou novo aqui, então se eu postei isso em um lugar errado lamento :)
Sarvan
2

Use System.DateTime.Now.ToUniversalTime(). Isso coloca sua leitura em um formato conhecido de milissegundo baseado em referência que elimina totalmente a mudança do dia, etc.

John Tobler
fonte
É bom saber, mas não é relevante para a pergunta que está sendo feita, que é sobre o tempo (medição da passagem do tempo), não sobre o tempo de comunicação precisa.
Página