Dapatkan waktu dalam milidetik menggunakan C #

132

Saya membuat program di mana saya perlu mendapatkan waktu dalam milidetik. Waktu, maksud saya angka yang tidak pernah sama dengan dirinya sendiri, dan selalu 1000 angka lebih besar dari sedetik yang lalu. Saya sudah mencoba mengubah DateTime.Nowke TimeSpandan mendapatkan TotalMillisecondsdari itu ... tapi saya pernah mendengar itu tidak sepenuhnya akurat.

Adakah cara yang lebih mudah untuk melakukan ini?

Kesatuan
sumber
Apakah Anda mengharapkan dua panggilan untuk selalu memimpin peningkatan nilai? Secara umum, panggilan yang lebih dekat daripada interval minimum yang dimungkinkan oleh resolusi timer akan menghasilkan nilai yang sama. Anda perlu menambahkan tiebreak Anda sendiri dalam bentuk serializer berpura-pura palsu.
Steven Sudit
16
"Angka yang tidak pernah sama dengan dirinya sendiri". Kedengarannya ... rumit. ;)
Mizipzor
1
NaN akan cocok dengan persyaratan itu sebenarnya. Meskipun "bukan angka", itu adalah tipe angka, dan itu tidak sama dengan itu sendiri.
Yay295

Jawaban:

78

Gunakan Stopwatchkelas.

Menyediakan serangkaian metode dan properti yang dapat Anda gunakan untuk secara akurat mengukur waktu yang telah berlalu.

Ada beberapa info bagus tentang penerapannya di sini:

Tes Kinerja: Pengukuran Jalankan Waktu Yang Tepat dengan System.Diagnostics.Stopwatch

RedFilter
sumber
8
stopwatch adalah bagian dari Diagnostics. Haruskah ini digunakan dalam kode nyata?
Andrey
Ini biasanya hanya akurat untuk sekitar 15 ms terdekat.
Steven Sudit
11
seberapa mahal harganya? mungkin kita harus stopwatch stopwatch :)
jb.
3
@ Seven, itu tergantung pada OS dan perangkat keras yang mendasarinya. Jika tersedia timer resolusi tinggi digunakan, yang merupakan kasus untuk semua desktop saat ini dan server berbasis x86 versi Windows yang saya ketahui. Periksa properti Frequency dan IsHighResolution untuk lebih jelasnya. Di tingkat OS, QueryPerformanceCounter dan QueryPerformanceFrequency adalah API tingkat rendah yang mendukung fungsi ini.
Chris Taylor
321
long milliseconds = DateTime.Now.Ticks / TimeSpan.TicksPerMillisecond;

Inilah sebenarnya bagaimana berbagai metode konversi Unix diimplementasikan di DateTimeOffsetkelas (.NET Framework 4.6+, .NET Standard 1.3+):

long milliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
Evan Mulawski
sumber
65
Judulnya adalah "dapatkan waktu dalam milidetik". Jawaban ini sangat membantu.
Aerospace
33
Yup, bagi kita yang mencari jawaban atas pertanyaan yang diajukan, ini sangat membantu, terima kasih.
user430788
1
Jika Anda ingin desimal (walaupun DateTime.Nowtidak sering "diperbarui"), tentu saja gunakan decimal milliseconds = DateTime.Now.Ticks / (decimal)TimeSpan.TicksPerMillisecond;saja.
Jeppe Stig Nielsen
1
Ini jauh lebih berguna daripada jawaban yang dipilih untuk hasil pencarian dan bahkan untuk apa yang saya kumpulkan dari pertanyaan awal.
bwoogie
1
Jawaban ini menyelamatkan hidupku. Mendapat kode serupa tetapi tidak berfungsi. Tidak tahu mengapa. Lalu saya melihat longtipe data di depan milidetik. Menggunakan inttentu akan meluap.
FisNaN
13

The DateTime.Ticksproperti mendapat jumlah kutu yang mewakili tanggal dan waktu.

10.000 Kutu adalah milidetik (10.000.000 kutu per detik).

Itay Karo
sumber
4
Tetapi resolusi Ticks sangat kurang dari 1 / 10.000, mungkin
1/62
2
@codymanix - dari 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
Tentu, tetapi sistem operasinya tidak memiliki resolusi setepat ini.
codymanix
6
@codymanix benar. Dengan analogi, Angstrom adalah satuan panjang; sepuluh miliar Angstrom menghasilkan satu meter. Anda dapat menulis fungsi yang melaporkan tinggi Anda sebagai bilangan bulat 64 bit di Angstroms, tetapi jika yang Anda miliki adalah metrestick yang akurat untuk sentimeter, maka fakta bahwa fungsi tersebut mewakili ketepatan sub-nanometer sama sekali tidak relevan. Digit yang kurang signifikan akan menjadi sampah.
Eric Lippert
4
@RedFilter: Jika Anda benar-benar mengetahui usia Anda hingga milidetik terdekat, Anda dapat mengatakan sesuatu seperti, "Ketika saya berkedip lagi, usia saya akan x milidetik." Masalah yang lebih dalam bukanlah komunikasi tetapi pengukuran: kelahiran Anda tidak mungkin diketahui bahkan sampai detik terdekat.
Steven Sudit
11

Saya menggunakan kelas berikut. Saya menemukannya di Internet sekali, dipostulatkan menjadi yang terbaik SEKARANG () .

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

Sumber tidak dikenal.

schmijos
sumber
5
FWIW, seluruh poin dari snippet yang umum digunakan ini, adalah membuat stempel waktu yang kompatibel dengan standar stempel waktu Unix. Untuk itu, sangat penting. Jika seseorang hanya ingin melakukan pengaturan waktu, itu tidak perlu mahal.
ToolmakerSteve
8

Anda dapat mencoba QueryPerformanceCountermetode asli. Lihat http://www.pinvoke.net/default.aspx/kernel32/QueryPerformanceCounter.html untuk informasi lebih lanjut. Inilah yang Stopwatchdigunakan kelas.

Lihat Bagaimana cara mendapatkan cap waktu presisi kutu di .NET / C #? untuk informasi lebih lanjut.

Stopwatch.GetTimestamp() memberikan akses ke metode ini:

public static long GetTimestamp() {
     if(IsHighResolution) {
         long timestamp = 0;
         SafeNativeMethods.QueryPerformanceCounter(out timestamp);
         return timestamp;
     }
     else {
         return DateTime.UtcNow.Ticks;
     }
 }
Pieter van Ginkel
sumber
1
AFAIK StopWatch menggunakan QueryPerformanceCounter secara internal jika tersedia
codymanix
Yap, implementasi internal Stopwatch.GetTimestamp()sebenarnya menyediakan akses ke metode itu.
Pieter van Ginkel
5

Saya menggunakan DateTime.Now.TimeOfDay.TotalMilliseconds (untuk hari ini), semoga ini membantu Anda juga.

Sarvan
sumber
1
itu tidak akan mengembalikan nilai yang meningkat (sesuai kebutuhan poster asli) karena TimeOfDay diatur ulang ke nol setiap hari pada tengah malam. Plus itu akan memiliki masalah potensial yang sama yang disebutkan poster ketika hanya menggunakan DateTime. Sekarang mendapatkan milidetik total dari itu.
Jim O'Neil
3
Jim O'Neil Saya setuju dengan Anda, itu sebabnya saya sebutkan "(untuk hari ini)" di posting saya ... Btw, solusi saya bekerja untuk masalah saya, karena masalah saya tidak spesifik tanggal, saya hanya perlu mendapatkan bagian milidetik untuk digunakan sebagai penghitung, jadi saya diposting di sini. Saya baru di sini, jadi jika saya mempostingnya di tempat yang salah saya minta maaf :)
Sarvan
2

Gunakan System.DateTime.Now.ToUniversalTime(). Yang menempatkan bacaan Anda dalam format milidetik berbasis referensi yang dikenal yang benar-benar menghilangkan perubahan hari, dll.

John Tobler
sumber
Baik untuk diketahui, tetapi tidak relevan dengan pertanyaan yang diajukan, yaitu tentang waktu (pengukuran waktu), bukan tentang waktu komunikasi yang akurat.
ToolmakerSteve