2010-04-09 14 views
13

Chcę mieć znacznik czasu dla dzienników na temat projektu Windows Mobile. Dokładność musi wynosić co najmniej sto milisekund.Milisekundy w DateTime.Now na .NET Compact Framework zawsze zero?

Jednak moje połączenie z DateTime.Now zwraca obiekt DateTime z ustawieniem właściwości Millisecond na zero. Również właściwość Ticks jest odpowiednio zaokrąglana.

Jak poprawić dokładność czasu?
Pamiętaj, że mój kod działa w Compact Framework, wersja 3.5. Używam urządzenia HTC touch Pro 2.

Na podstawie odpowiedzi z MusiGenesis Utworzono następujące klasy, która rozwiązała ten problem:

/// <summary> 
/// A more precisely implementation of some DateTime properties on mobile devices. 
/// </summary> 
/// <devdoc>Tested on a HTC Touch Pro2.</devdoc> 
public static class DateTimePrecisely 
{ 
    /// <summary> 
    /// Remembers the start time when this model was created. 
    /// </summary> 
    private static DateTime _start = DateTime.Now; 
    /// <summary> 
    /// Remembers the system uptime ticks when this model was created. This 
    /// serves as a more precise time provider as DateTime.Now can do. 
    /// </summary> 
    private static int _startTick = Environment.TickCount; 

    /// <summary> 
    /// Gets a DateTime object that is set exactly to the current date and time on this computer, expressed as the local time. 
    /// </summary> 
    /// <returns></returns> 
    public static DateTime Now 
    { 
     get 
     { 
      return _start.AddMilliseconds(Environment.TickCount - _startTick); 
     } 
    } 
} 
+2

Nie trzeba ponownie podawać pytania słowem "[SOLVED]". Możesz powiedzieć, że pytanie ma akceptowaną odpowiedź przez żółty licznik odpowiedzi na pierwszej stronie lub w wynikach wyszukiwania. – spoulson

+2

Jako źródło tego, powinienem wspomnieć, że ta klasa prawie na pewno "odpłynie" od wartości zwróconej przez zwykłą 'DateTime.Now', prawdopodobnie nawet o kilka sekund (lub nawet o wiele więcej) w trakcie dzień.Możesz to sprawdzić po prostu ustawiając właściwość klasy _start, czekając trochę czasu (dzień lub cokolwiek innego) i porównując 'DateTime.Now' do' DateTimePrecisely.Now'. – MusiGenesis

+1

Jeśli uznasz, że wartość dryfu jest nie do zaakceptowania, możesz dodać metodę "Reset", która pobiera świeże wartości dla '_start' i' _startTick', i wywoływać ją okresowo. Pozwoli to na długoterminową synchronizację z zegarem systemowym, jednocześnie dając (rzekomo) milisekundową rozdzielczość. Lub użyj kodu 'ctacke'. – MusiGenesis

Odpowiedz

14

Environment.TickCount zwróci liczbę milisekund, którą system Windows (lub Windows Mobile) uruchomił od czasu ostatniego restartu.

Aby to wykorzystać, dodać te dwie zmienne forma poziomie do kodu:

private DateTime _start; 
private int _startTick; 

W przypadku ładowania formularza, w tym celu:

private void Form1_Load(object sender, EventArgs e) 
{ 
    _start = DateTime.Now; 
    _startTick = Environment.TickCount; 
} 

Gdy trzeba obiekt DateTime z milisekundach , to zrobić:

DateTime timeStamp = 
    _start.AddMilliseconds(Environment.TickCount - _startTick); 

Environment.TickCount jest int i ta wartość "zawinie się" do Int32.MinValue po około 25 dniach. Jeśli Twoje urządzenie będzie działało tak długo bez ponownego uruchamiania, będziesz chciał dodać wartość sprawdzania dla wartości Environment.TickCount, która jest mniejsza niż ostatnia odczytana wartość, i zresetować zarówno _start, jak i _start i _startTick, jeśli tak.

+0

+1. to załatwiło sprawę. Szkoda, że ​​microsoft (lub HTC?) Nie robi tego w swoim kodzie. – Marcel

+3

To jest awaria HTC, a nie Microsoft. Od producenta OEM zależy czas. – ctacke

+0

Proszę mi pomóc, ponieważ nie widzę, jak to zwróci czas z większą dokładnością. Będziesz miał "więcej cyfr", ale to wszystko, ponieważ czas rozpoczęcia już nie zawiera części ułamkowych sekund, więc dodajesz tylko "wyimaginowane" liczby. Jeśli jest używany w dzienniku, można zobaczyć czas, jaki upłynął między wpisami dziennika, ale nie można go porównać z czasem innych systemów. – HoGo

1

Główną alternatywą jest klasa System.Diagnostics.Stopwatch.

Jest dostępny w CE, ale należy pamiętać o właściwości IsHighResolution. Prawdopodobnie jest to Fałsz na urządzeniu, ale sprawdź.

Jest tak dokładny, jak to się stanie bez P/Invoke.

-3

W regularnych ramach v2.0 można użyć DateTime.Now.ToString ("yyyy-MM-dd HH: mm: ss.fff"), aby uzyskać milisekundy. Więcej f oznacza większą precyzję.

+0

Nieprawda w CF. Zobacz inne odpowiedzi na pytanie. – ctacke

Powiązane problemy