Ottieni tempo in millisecondi usando C #


132

Sto realizzando un programma in cui ho bisogno di ottenere il tempo in millisecondi. Per tempo, intendo un numero che non è mai uguale a se stesso, ed è sempre più grande di 1000 numeri rispetto a un secondo fa. Ho provato a convertirmi DateTime.Nowin a TimeSpane ottenere TotalMillisecondsda quello ... ma ho sentito che non è perfettamente preciso.

C'è un modo più semplice per farlo?


Ti aspetti che due chiamate portino sempre valori crescenti? In generale, le chiamate più vicine all'intervallo minimo consentito dalla risoluzione del timer produrranno lo stesso valore. Dovresti aggiungere il tuo tiebreaker sotto forma di un serializzatore di precisione falso.
Steven Sudit,

16
"Un numero che non è mai uguale a se stesso". Sembra ... complicato. ;)
Mizipzor,

1
NaN si adatterebbe effettivamente a tale requisito. Nonostante sia "non un numero", è un tipo di numero e non è uguale a se stesso.
Yay295

Risposte:


78

Usa la Stopwatchclasse.

Fornisce una serie di metodi e proprietà che è possibile utilizzare per misurare accuratamente il tempo trascorso.

Ci sono alcune buone informazioni su come implementarlo qui:

Test delle prestazioni: misurazioni precise del tempo di esecuzione con System.Diagnostics.Stopwatch


8
il cronometro fa parte della diagnostica. Dovrebbe essere usato in codice reale?
Andrey,


Questo è normalmente accurato solo per i 15ms circa.
Steven Sudit,

11
quanto costa però? forse dovremmo cronometrare un cronometro :)
jb.

3
@Steven, dipende dal sistema operativo e dall'hardware sottostante. Se disponibile, viene utilizzato un timer ad alta risoluzione, che è il caso di tutte le attuali versioni di Windows x86 basate su desktop e server di cui sono a conoscenza. Controllare le proprietà Frequenza e IsHighResolution per ulteriori dettagli. A livello di sistema operativo, QueryPerformanceCounter e QueryPerformanceFrequency sono le API di basso livello che supportano questa funzionalità.
Chris Taylor,

321
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;

Questo è in realtà il modo in cui i vari metodi di conversione Unix sono implementati nella DateTimeOffsetclasse (.NET Framework 4.6+, .NET Standard 1.3+):

long milliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();

65
Il titolo è "prendi il tempo in millisecondi". Questa risposta è utile
Aerospace

33
Sì, per quelli di noi che cercano una risposta alla domanda come posta, questo è stato molto utile, grazie.
user430788

1
Se vuoi i decimali (anche se DateTime.Nownon vengono "aggiornati" molto spesso), ovviamente usa decimal milliseconds = DateTime.Now.Ticks / (decimal)TimeSpan.TicksPerMillisecond;invece.
Jeppe Stig Nielsen

1
Questo è molto più utile della risposta selezionata per i risultati della ricerca e anche per quello che raccolgo dalla domanda originale.
bwoogie,

1
Questa risposta mi ha salvato la vita. Ha un codice simile ma non funziona. Non riuscivo a capire perché. Poi ho visto il longtipo di dati davanti a millisecondi. Usando intsicuramente finirà per traboccare.
FisNaN,

13

La DateTime.Ticksproprietà ottiene il numero di tick che rappresentano la data e l'ora.

10.000 tick è un millisecondo (10.000.000 di tick al secondo).


4
Ma la risoluzione delle zecche è molto inferiore a 1/10000, forse
1/62

2
@codymanix - da 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
Certo che lo è, ma il sistema operativo non ha la risoluzione per essere così esatto.
codymanix,

6
@codymanix è corretto. Per analogia, un Angstrom è un'unità di lunghezza; dieci miliardi di Angstrom fanno un metro. Potresti scrivere una funzione che riporta la tua altezza come numero intero a 64 bit in Angstrom, ma se tutto ciò che hai è un metrestick accurato al centimetro, allora il fatto che la funzione rappresenti una precisione sub-nanometrica è completamente irrilevante. Le cifre meno significative saranno spazzatura.
Eric Lippert,

4
@RedFilter: se in realtà conoscessi la tua età al millisecondo più vicino, potresti concepibilmente dire qualcosa del tipo "Quando sbatto le palpebre di nuovo, la mia età sarà di x millisecondi". Il problema più profondo non è la comunicazione ma la misurazione: è improbabile che la tua nascita sia nota anche al secondo più vicino.
Steven Sudit,

11

Uso la seguente classe. L'ho trovato su Internet una volta, postulato per essere il migliore ADESSO () .

/// <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 sconosciuta


5
FWIW, il punto centrale di questo frammento comunemente usato, è creare un timestamp compatibile con lo standard di timestamp Unix. Per questo, è vitale. Se uno vuole solo fare i tempi, è inutilmente costoso.
ToolmakerSteve

8

Puoi provare il QueryPerformanceCountermetodo nativo. Vedere http://www.pinvoke.net/default.aspx/kernel32/QueryPerformanceCounter.html per ulteriori informazioni. Questo è ciò che Stopwatchusa la classe.

Vedi Come ottenere il timestamp della precisione tick in .NET / C #? per maggiori informazioni.

Stopwatch.GetTimestamp() dà accesso a questo metodo:

public static long GetTimestamp() {
     if(IsHighResolution) {
         long timestamp = 0;
         SafeNativeMethods.QueryPerformanceCounter(out timestamp);
         return timestamp;
     }
     else {
         return DateTime.UtcNow.Ticks;
     }
 }

1
AFAIK StopWatch utilizza QueryPerformanceCounter internamente se disponibile
codymanix,

Sì, l'implementazione interna di Stopwatch.GetTimestamp()effettivamente fornisce l'accesso a quel metodo.
Pieter van Ginkel,

5

Ho usato DateTime.Now.TimeOfDay.TotalMilliseconds (per il giorno corrente), spero che ti aiuti anche.


1
che non restituirà valori crescenti (come richiesto dal poster originale) poiché TimeOfDay viene reimpostato su zero ogni giorno a mezzanotte. Inoltre avrebbe gli stessi potenziali problemi menzionati dal poster quando si utilizzava solo DateTime. Ora si ottengono i millisecondi totali.
Jim O'Neil,

3
Jim O'Neil Sono d'accordo con te, ecco perché ho menzionato "(per il giorno corrente)" nel mio post ... A proposito, la mia soluzione ha funzionato per il mio problema, poiché il mio problema non è specifico per la data, dovevo semplicemente ottenere la parte Millisecondi da utilizzare come contatore, quindi l'ho pubblicata qui. Sono nuovo qui, quindi se l'ho pubblicato in un posto sbagliato mi dispiace :)
Sarvan

2

Usa System.DateTime.Now.ToUniversalTime(). Questo mette la tua lettura in un formato millisecondo noto di riferimento che elimina totalmente il cambio di giorno, ecc.


Buono a sapersi, ma non pertinente alla domanda posta, che riguarda il tempo (misurazione del passaggio del tempo), non il tempo di comunicare con precisione.
ToolmakerSteve
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.