2010-06-29 41 views
6

Related to my previous question, nhưng với C#, tôi cần thời gian hệ thống chính xác bao gồm mili giây.Thời gian hệ thống Windows với mili giây chính xác

Chức năng thời gian C# có độ chính xác lên đến 10 đến 15 mili giây, nhưng không chính xác 1 mili giây.

Trường hợp tương tự với bộ đếm hiệu suất Hàng đợi. Có cách nào khác để có được độ chính xác lên đến mili giây chính xác không?

Trả lời

7

Windows không muốn lãng phí điện bằng cách cập nhật đồng hồ hệ thống 1000 lần mỗi giây, do đó, mặc định chỉ cập nhật 60-100 lần mỗi giây. Nếu bạn đặt hẹn giờ đa phương tiện thành 1ms, bạn có thể nhận được độ phân giải 1ms từ đồng hồ, nhưng điều đó không được khuyến nghị.

Để giải thích thêm về tiết kiệm điện, điều gì sẽ xảy ra khi CPU không hoạt động trong một khoảng thời gian là nó có thể chuyển sang trạng thái rất yếu. Bất cứ khi nào nó bị gián đoạn (ví dụ như tăng các đồng hồ), nó phải rời khỏi trạng thái công suất rất thấp và sử dụng rất nhiều điện để cấp nguồn cho toàn bộ CPU để dịch vụ ngắt. Nói cách khác, sức mạnh bổ sung không phải là gia tăng các dấu tích đồng hồ, nó giữ CPU tỉnh táo để làm điều đó.

Vì máy tính xách tay của tôi sử dụng 10W khi không hoạt động khi tần số xung nhịp là 60Hz và 11W khi là 1000Hz và tôi có thời lượng pin 300 phút, đồng hồ chậm hơn đó cho tôi gần 30 phút sử dụng pin!

+0

Bạn đang nói về các ngắt hạt nhân? http://lwn.net/Articles/145973/ – Nitrodist

+0

Nitrodist: Vâng, đó là giải thích về cùng một vấn đề. – Gabe

+0

Anh ấy đang nói về việc đánh dấu hạt nhân, một dấu tích hạt nhân là một phần cứng được lập lịch trình (CPU) 'ngắt quãng thời gian'. Tuy nhiên, Windows vẫn chưa có hiệu quả về điện năng (hiệu suất kém hơn 50% so với Android, và ít hơn 20% so với hệ điều hành Mac), nhưng không có lý do gì khiến nó trở nên tồi tệ hơn. Các dấu tick của hạt nhân được sử dụng để gọi các callback thời gian đã hết hạn (hoặc coalesced), cập nhật lại luồng/lập lịch trình quy trình và tăng số lượng đánh dấu hệ điều hành toàn cầu. –

6

Hãy thử System.Diagnostics.Stopwatch để có thời gian có độ phân giải cao.

Nếu phần cứng cài đặt và hệ điều hành hỗ trợ độ phân giải cao hiệu suất truy cập, sau đó lớp Stopwatch sử dụng mà truy cập để đo thời gian trôi qua. Nếu không, lớp Đồng hồ bấm giờ sử dụng bộ hẹn giờ hệ thống để đo thời gian đã trôi qua .

Hãy thử bản gốc DateTime.Ticks để có độ chính xác của hệ thống tối đa một trăm nano giây; 1 mili giây = 10000 bọ ve.

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

Anh ấy yêu cầu thời gian hệ thống. Đồng hồ bấm giờ chỉ cho thời gian trôi qua. – Gabe

+3

Gọi 'DateTime.Ticks' không chính xác hơn' DateTime.Millisecond'. Trong nội bộ, 'DateTime.Millisecond' gọi' DateTime.Ticks' –

+0

Đúng.Tôi đã chỉ ra rằng theo MSDN và thử nghiệm thô này rằng nó là chính xác ít nhất là độ phân giải mili giây mà người hỏi đang yêu cầu; do đó bên cạnh Console.Output của DateTime như một chuỗi bên cạnh Ticks. – xcud

8

Bạn có thể sử dụng this DateTimePrecise class để có được một thời gian chính xác cao trong .NET

CẬP NHẬT
Liên kết CodeProject không còn làm việc. Tôi đã lấy mã số from archive.org và nhúng mã vào đây để tham khảo trong tương lai. Mã này được bao gồm ở đây "như là", chính xác cách nó được đưa vào trang CodeProject.

DateTimePrecise là dễ dàng để sử dụng như DateTime.Now, ngoại trừ việc DateTimePrecise.Now là một phương pháp dụ thay vì một phương pháp tĩnh, vì vậy trước tiên bạn phải tạo một DateTimePrecise.

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

Bạn có lớp học không? Liên kết không còn hoạt động nữa. Cảm ơn –

+0

@ Răzvan Tôi đã khôi phục lại mã từ archive.org và thêm nó vào câu trả lời của tôi. Cảm ơn bạn đã chỉ ra rằng đó là một liên kết chết. –

+2

+1 để phục sinh –

Các vấn đề liên quan