2010-06-29 9 views
6

Related to my previous question,하지만 C#을 사용하면 밀리 초를 포함한 정확한 시스템 시간이 필요합니다.밀리 초 단위의 Windows 시스템 시간

C# 시간 함수의 정확도는 최대 10-15 밀리 초이지만 정확히 1 밀리 초는 아닙니다.

대기열 성능 카운터도 마찬가지입니다. 정확한 밀리 초 단위의 정확도를 얻는 다른 방법이 있습니까?

답변

7

Windows는 기본 만 초당 60 ~ 100 번을 업데이트하므로, 시스템 클럭 초당 1000 배를 업데이트하여 전기를 낭비하고 싶지 않습니다. 멀티미디어 타이머를 1ms로 설정하면 시계에서 1ms 해상도를 얻을 수 있지만 권장하지는 않습니다.

전력 절약에 대해 자세히 설명하기 위해 CPU가 일정 기간 동안 유휴 상태 일 때 매우 저전력 상태가 될 수 있다는 점이 무엇인지 자세히 설명합니다. 인터럽트가 발생할 때마다 (예를 들어 시계 틱을 증가시키기 위해), 그것은 매우 저전력 상태를 떠나야하고, 많은 인터 럽션을 처리하기 위해 전체 CPU에 전력을 공급해야한다. 즉, 추가 전력은 시계 틱을 증가시키는 것이 아니라 CPU가 깨어있게하는 것입니다.

내 랩톱은 클록 주파수가 60Hz이고 11W가 1000Hz 인 경우 유휴 상태에서 10W를 사용하고 배터리 수명이 300 분인 저속 시계는 배터리 수명을 거의 30 분 연장합니다.

+0

커널 인터럽트에 대해 이야기하고 있습니까? http://lwn.net/Articles/145973/ – Nitrodist

+0

Nitrodist : 네, 같은 문제에 대한 설명입니다. – Gabe

+0

그는 커널 틱에 대해 이야기하고 있으며 커널 틱은 예정된 하드웨어 (CPU)'타이머 인터럽트 '입니다. Windows는 전기 효율이 좋지 않지만 (안드로이드보다 50 % 덜 효율적이고 맥 OS보다 20 % 덜 효율적), 실제로 악화시킬 이유는 없습니다. 커널 틱은 만료 (또는 통합) 된 타이머 콜백을 호출하고 스레드/프로세스 스케줄링을 다시 업데이트하며 전역 OS 틱 수를 증가시키는 데 사용됩니다. –

6

고해상도 타이밍을 위해 System.Diagnostics.Stopwatch을 시도하십시오. 설치된 하드웨어 및 운영 체제가 고해상도 성능 카운터를 지원하는 경우

는 다음 스톱워치 클래스 카운터 경과 시간을 측정하는 것을 사용한다. 그렇지 않으면 Stopwatch 클래스는 시스템 타이머를 사용하여 경과 된 시간을 측정합니다 ( ).

네이티브 DateTime.Ticks을 최대 100 나노초의 시스템 시간 정확도로 사용해보십시오. 1 밀리 초 = 10000 틱.

while (true) 
{ 
    System.Threading.Thread.Sleep(1); 

    Console.WriteLine("{0} {1}", 
     System.DateTime.Now.Ticks, 
     System.DateTime.Now.ToString("ss:fff")); 
} 

PS > .\test.exe 
    634134152924322129 52:432 
    634134152924332129 52:433 
    634134152924342130 52:434 
    634134152924352130 52:435 
    634134152924362131 52:436 
    634134152924372131 52:437 
    634134152924382132 52:438 
    634134152924392133 52:439 
    634134152924402133 52:440 
    634134152924412134 52:441 
    634134152924422134 52:442 
    634134152924432135 52:443 
+3

그는 시스템 시간을 요청했습니다. 스톱워치는 그냥 경과 시간을 알려줍니다. – Gabe

+3

'DateTime.Ticks' 호출은'DateTime.Millisecond'보다 정확하지 않습니다. 내부적으로,'DateTime.Millisecond'는'DateTime.Ticks'을 호출합니다 –

+0

.MSDN과이 거친 테스트에 따르면 질문자가 요구하는 최소 밀리 초 해상도가 정확하다는 것을 지적했습니다. 따라서 Ticks와 나란히 문자열로서 DateTime을 Console.Output하여 나란히 배치합니다. – xcud

8

당신은 CodeProject의 링크가 더 이상 작동
.NET

UPDATE에 고정밀 시간을 얻을 수 this DateTimePrecise class를 사용할 수 있습니다. 나는 코드 from archive.org을 가져 와서 나중에 참조 할 수 있도록 여기에 임베드했다. 이 코드는 CodeProject 페이지에 정확히 포함 된 그대로 "있는 그대로"여기에 포함됩니다. 그 DateTimePrecise.Now 대신 정적 메서드의 인스턴스 방법은, 그래서 당신이 먼저 DateTimePrecise를 인스턴스화 할 필요가 제외

DateTimePreciseDateTime.Now으로 사용하기 쉽습니다.

using System.Diagnostics; 

/// DateTimePrecise provides a way to get a DateTime that exhibits the 
/// relative precision of 
/// System.Diagnostics.Stopwatch, and the absolute accuracy of DateTime.Now. 
public class DateTimePrecise 
{ 
    /// Creates a new instance of DateTimePrecise. 
    /// A large value of synchronizePeriodSeconds may cause arithmetic overthrow 
    /// exceptions to be thrown. A small value may cause the time to be unstable. 
    /// A good value is 10. 
    /// synchronizePeriodSeconds = The number of seconds after which the 
    /// DateTimePrecise will synchronize itself with the system clock. 
    public DateTimePrecise(long synchronizePeriodSeconds) 
    { 
     Stopwatch = Stopwatch.StartNew(); 
     this.Stopwatch.Start(); 

     DateTime t = DateTime.UtcNow; 
     _immutable = new DateTimePreciseSafeImmutable(t, t, Stopwatch.ElapsedTicks, 
      Stopwatch.Frequency); 

     _synchronizePeriodSeconds = synchronizePeriodSeconds; 
     _synchronizePeriodStopwatchTicks = synchronizePeriodSeconds * 
      Stopwatch.Frequency; 
     _synchronizePeriodClockTicks = synchronizePeriodSeconds * 
      _clockTickFrequency; 
    } 

    /// Returns the current date and time, just like DateTime.UtcNow. 
    public DateTime UtcNow 
    { 
     get 
     { 
      long s = this.Stopwatch.ElapsedTicks; 
      DateTimePreciseSafeImmutable immutable = _immutable; 

      if (s < immutable._s_observed + _synchronizePeriodStopwatchTicks) 
      { 
       return immutable._t_base.AddTicks(((
        s - immutable._s_observed) * _clockTickFrequency)/(
        immutable._stopWatchFrequency)); 
      } 
      else 
      { 
       DateTime t = DateTime.UtcNow; 

       DateTime t_base_new = immutable._t_base.AddTicks(((
        s - immutable._s_observed) * _clockTickFrequency)/(
        immutable._stopWatchFrequency)); 

       _immutable = new DateTimePreciseSafeImmutable(
        t, 
        t_base_new, 
        s, 
        ((s - immutable._s_observed) * _clockTickFrequency * 2) 
        /
        (t.Ticks - immutable._t_observed.Ticks + t.Ticks + 
         t.Ticks - t_base_new.Ticks - immutable._t_observed.Ticks) 
       ); 

       return t_base_new; 
      } 
     } 
    } 

    /// Returns the current date and time, just like DateTime.Now. 
    public DateTime Now 
    { 
     get 
     { 
      return this.UtcNow.ToLocalTime(); 
     } 
    } 

    /// The internal System.Diagnostics.Stopwatch used by this instance. 
    public Stopwatch Stopwatch; 

    private long _synchronizePeriodStopwatchTicks; 
    private long _synchronizePeriodSeconds; 
    private long _synchronizePeriodClockTicks; 
    private const long _clockTickFrequency = 10000000; 
    private DateTimePreciseSafeImmutable _immutable; 
} 

internal sealed class DateTimePreciseSafeImmutable 
{ 
    internal DateTimePreciseSafeImmutable(DateTime t_observed, DateTime t_base, 
     long s_observed, long stopWatchFrequency) 
    { 
     _t_observed = t_observed; 
     _t_base = t_base; 
     _s_observed = s_observed; 
     _stopWatchFrequency = stopWatchFrequency; 
    } 
    internal readonly DateTime _t_observed; 
    internal readonly DateTime _t_base; 
    internal readonly long _s_observed; 
    internal readonly long _stopWatchFrequency; 
} 
+0

수업이 있습니까? 링크가 더 이상 작동하지 않습니다. 감사합니다 –

+0

@ Răzvan 나는 archive.org에서 코드를 부활시키고 그것을 내 대답에 추가했습니다. 그것이 죽은 연결 이었다는 것을 지적하기를위한 감사합니다. –

+2

부활 +1 +1 –

관련 문제