Domanda

Ho appena incontrato un certo comportamento imprevisto con DateTime.UtcNow mentre facendo alcuni test di unità. Sembra che quando si chiama DateTime.Now/UtcNow in rapida successione, sembra dare indietro lo stesso valore per un intervallo di tempo più lungo del previsto, piuttosto che l'acquisizione incrementi più precisi al millisecondo.

So che c'è una classe Stopwatch che sarebbe più adatto per fare misure di tempo precisi, ma ero curioso di sapere se qualcuno potrebbe spiegare questo comportamento in DateTime? C'è una precisione ufficiale documentato per DateTime.Now (per esempio, una precisione di 50 ms?)? Perché sarebbe DateTime.Now essere fatta meno preciso di quello che la maggior parte degli orologi CPU in grado di gestire? Forse è solo progettato per il più basso denominatore comune CPU?

public static void Main(string[] args)
{
    var stopwatch = new Stopwatch();
    stopwatch.Start();
    for (int i=0; i<1000; i++)
    {
        var now = DateTime.Now;
        Console.WriteLine(string.Format(
            "Ticks: {0}\tMilliseconds: {1}", now.Ticks, now.Millisecond));
    }

    stopwatch.Stop();
    Console.WriteLine("Stopwatch.ElapsedMilliseconds: {0}",
        stopwatch.ElapsedMilliseconds);

    Console.ReadLine();
}
È stato utile?

Soluzione

  

Perché sarebbe DateTime.Now essere fatta meno preciso di quello che la maggior parte degli orologi CPU in grado di gestire?

Un buon orologio dovrebbe essere sia precisa e accurate ; quelli sono diversi. Come la vecchia barzelletta va, un orologio fermo è esattamente preciso due volte al giorno, un orologio di un minuto lenta non è mai preciso in qualsiasi momento. Ma l'orologio di un minuto lento è sempre preciso al minuto più vicino, mentre un orologio fermo non ha la precisione utile a tutti.

Perché il DateTime essere precisa per, diciamo un microsecondo quando non può eventualmente essere accurate al microsecondo? La maggior parte delle persone non hanno alcuna fonte di segnali di tempo ufficiali che sono accurate al microsecondo. Pertanto preavviso di sei cifre dopo il punto decimale di di precisione , gli ultimi cinque dei quali sono spazzatura sarebbe sdraiato .

Ricordate, lo scopo del DateTime è quello di rappresentano una data e ora . timing di alta precisione non è affatto lo scopo di DateTime; come si nota, che è lo scopo di cronometro. Lo scopo di DateTime è quello di rappresentare una data e un'ora per scopi come la visualizzazione del tempo corrente per l'utente, calcolando il numero di giorni fino al prossimo Martedì, e così via.

In breve, "a che ora è?" e "quanto tempo ha fatto che prendere?" sono domande completamente diverse; non utilizzare uno strumento progettato per rispondere a una domanda a cui rispondere all'altro.

Grazie per la domanda; questo renderà un buon articolo di blog! : -)

Altri suggerimenti

precisione di DateTime è in qualche modo specifico per il sistema è in esecuzione su. La precisione è legata alla velocità di un cambio di contesto, che tende ad essere circa 15 o 16 ms. (Sul mio sistema, in realtà è di circa 14 ms dalla mia prova, ma ho visto alcuni laptop dove è più vicino a 35-40 accuratezza ms.)

Peter Bromberg ha scritto un articolo sui tempi del codice di alta precisione in C #, che discute questo .

Vorrei un Datetime.Now precisa :), così ho cucinato questo in su:

public class PreciseDatetime
{
    // using DateTime.Now resulted in many many log events with the same timestamp.
    // use static variables in case there are many instances of this class in use in the same program
    // (that way they will all be in sync)
    private static readonly Stopwatch myStopwatch = new Stopwatch();
    private static System.DateTime myStopwatchStartTime;

    static PreciseDatetime()
    {
        Reset();

        try
        {
            // In case the system clock gets updated
            SystemEvents.TimeChanged += SystemEvents_TimeChanged;
        }
        catch (Exception)
        {                
        }
    }

    static void SystemEvents_TimeChanged(object sender, EventArgs e)
    {
        Reset();
    }

    // SystemEvents.TimeChanged can be slow to fire (3 secs), so allow forcing of reset
    static public void Reset()
    {
        myStopwatchStartTime = System.DateTime.Now;
        myStopwatch.Restart();
    }

    public System.DateTime Now { get { return myStopwatchStartTime.Add(myStopwatch.Elapsed); } }
}

MSDN vi accorgerete che la DateTime.Now ha un approssimativa risoluzione di 10 millisecondi su tutti i sistemi operativi NT.

La precisione effettiva è dipendente dall'hardware. Meglio di precisione può essere ottenuto utilizzando QueryPerformanceCounter .

Per quel che vale, a corto di realtà controllando la fonte .NET, Eric Lippert fornito un commento su questa domanda SO dicendo che DateTime indica una circa 30 ms. Il ragionamento per non essere nanosecondo accurata, nelle sue parole, è che "non ha bisogno di essere".

da MSDN documentazione :

  

La risoluzione di questa proprietà   dipende dal timer di sistema.

Essi affermano inoltre che la risoluzione approssimativa su Windows NT 3.5 e versioni successive è di 10 ms:)

  

La risoluzione di questa proprietà dipende dal timer di sistema, che   dipende dal sistema operativo sottostante. Esso tende ad essere tra 0,5   e 15 millisecondi.

Come risultato, ripetute chiamate alla struttura ora in un breve intervallo di tempo, ad esempio in un ciclo, possono restituire lo stesso valore.

MSDN collegamento

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top