Obtenga tiempo en milisegundos con C #

132

Estoy haciendo un programa en el que necesito obtener el tiempo en milisegundos. Por tiempo, me refiero a un número que nunca es igual a sí mismo, y siempre es 1000 números más grande que hace un segundo. He intentado convertir DateTime.Nowa ay TimeSpanobtener TotalMillisecondseso ... pero he oído que no es perfectamente exacto.

¿Hay una manera más fácil de hacer esto?

Entidad
fuente
¿Espera que dos llamadas conduzcan siempre a valores crecientes? En general, las llamadas más cercanas al intervalo mínimo que permite la resolución del temporizador producirán el mismo valor. Tendría que agregar su propio desempate en forma de un serializador de precisión falsa.
Steven Sudit
16
"Un número que nunca es igual a sí mismo". Eso suena ... complicado. ;)
Mizipzor
1
NaN cumpliría ese requisito en realidad. A pesar de ser "no un número", es un tipo de número y no es igual a sí mismo.
Yay295

Respuestas:

78

Usa la Stopwatchclase.

Proporciona un conjunto de métodos y propiedades que puede usar para medir con precisión el tiempo transcurrido.

Hay buena información sobre cómo implementarlo aquí:

Pruebas de rendimiento: mediciones precisas del tiempo de ejecución con System.Diagnostics.Stopwatch

RedFilter
fuente
8
El cronómetro es parte de Diagnóstico. ¿Debería usarse en código real?
Andrey
55
@Andrey - stackoverflow.com/questions/2805362/…
John Rasch
Esto normalmente solo es exacto a los 15 ms más cercanos.
Steven Sudit
11
¿Qué tan caro es? tal vez deberíamos detener un cronómetro :)
jb.
3
@ Steven, eso depende del sistema operativo y del hardware subyacente. Si está disponible, se utiliza un temporizador de alta resolución, que es el caso de todas las versiones actuales de Windows x86 basadas en el escritorio y el servidor que conozco. Verifique las propiedades de Frecuencia e IsHighResolution para más detalles. En el nivel del sistema operativo, QueryPerformanceCounter y QueryPerformanceFrequency son las API de bajo nivel que respaldan esta funcionalidad.
Chris Taylor
321
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;

Así es como se implementan los diversos métodos de conversión de Unix en la DateTimeOffsetclase (.NET Framework 4.6+, .NET Standard 1.3+):

long milliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
Evan Mulawski
fuente
65
El título es "obtener tiempo en milisegundos". Esta respuesta es útil.
Aeroespacial
33
Sí, para aquellos de nosotros que buscamos una respuesta a la pregunta planteada, esto fue muy útil, gracias.
user430788
1
Si desea decimales (incluso si DateTime.Nowno se "actualiza" muy a menudo), por supuesto, use decimal milliseconds = DateTime.Now.Ticks / (decimal)TimeSpan.TicksPerMillisecond;en su lugar.
Jeppe Stig Nielsen
1
Esto es mucho más útil que la respuesta seleccionada para los resultados de búsqueda e incluso para lo que deduzco de la pregunta original.
bwoogie
1
Esta respuesta me salvó la vida. Tengo un código similar pero no funciona. No pude entender por qué. Entonces vi el longtipo de datos frente a milisegundos. El uso intciertamente se desbordará.
FisNaN
13

La DateTime.Tickspropiedad obtiene el número de ticks que representan la fecha y la hora.

10,000 ticks es un milisegundo (10,000,000 ticks por segundo).

Itay Karo
fuente
44
Pero la resolución de Ticks es muy inferior a 1 / 10000s, tal vez 1 /
62s
2
@codymanix - de 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
55
Claro que sí, pero el sistema operativo no tiene la resolución para ser tan exacto.
codymanix
66
@codymanix es correcto. Por analogía, un Angstrom es una unidad de longitud; diez mil millones de Angstroms hacen un metro. Podría escribir una función que informe su altura como un entero de 64 bits en Angstroms, pero si todo lo que tiene es una metacontrol precisa al centímetro, entonces el hecho de que la función represente una precisión subnanométrica es completamente irrelevante. Los dígitos menos significativos serán basura.
Eric Lippert
44
@RedFilter: Si realmente supiera su edad al milisegundo más cercano, podría decir algo como: "Cuando parpadee de nuevo, mi edad será x milisegundos". El problema más profundo no es la comunicación sino la medición: es poco probable que se conozca su nacimiento incluso en el segundo más cercano.
Steven Sudit
11

Yo uso la siguiente clase. Lo encontré en Internet una vez, postulado para ser el mejor AHORA () .

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

Fuente desconocida

schmijos
fuente
55
FWIW, el objetivo de este fragmento de uso común, es hacer una marca de tiempo que sea compatible con el estándar de marca de tiempo de Unix. Para eso es vital. Si uno solo quiere cronometrar, es innecesariamente costoso.
ToolmakerSteve
8

Puedes probar el QueryPerformanceCountermétodo nativo. Consulte http://www.pinvoke.net/default.aspx/kernel32/QueryPerformanceCounter.html para obtener más información. Esto es lo que Stopwatchusa la clase.

Consulte ¿Cómo obtener la marca de tiempo de precisión de marca en .NET / C #? para más información.

Stopwatch.GetTimestamp() da acceso 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
fuente
1
AFAIK StopWatch utiliza QueryPerformanceCounter internamente si está disponible
codymanix
Sí, la implementación interna de Stopwatch.GetTimestamp()realmente proporciona acceso a ese método.
Pieter van Ginkel
5

Utilicé DateTime.Now.TimeOfDay.TotalMilliseconds (para el día actual), espero que también te ayude.

Sarvan
fuente
1
eso no devolverá valores crecientes (como requería el póster original) ya que TimeOfDay se restablece a cero todos los días a la medianoche. Además, tendría los mismos problemas potenciales que el póster mencionó cuando solo usó DateTime. Ahora obtendrá el total de milisegundos de eso.
Jim O'Neil
3
Jim O'Neil Estoy de acuerdo con usted, por eso mencioné "(para el día actual)" en mi publicación ... Por cierto, mi solución funcionó para mi problema, ya que mi problema no es específico de la fecha, simplemente necesitaba obtener la parte de milisegundos se usará como contador, así que la publiqué aquí. Soy nuevo aquí, así que si lo publiqué en un lugar equivocado, lo siento :)
Sarvan
2

Uso System.DateTime.Now.ToUniversalTime(). Eso coloca su lectura en un formato de milisegundos basado en referencias conocido que elimina totalmente el cambio de día, etc.

John Tobler
fuente
Es bueno saberlo, pero no es relevante para la pregunta que se hace, que trata sobre el tiempo (medición del paso del tiempo), no sobre la comunicación precisa del tiempo.
ToolmakerSteve