Системное время Windows с точностью до миллисекунды - PullRequest
6 голосов
/ 29 июня 2010

В связи с моим предыдущим вопросом , но с C # мне нужно точное системное время, включая миллисекунды.

Функция времени C # имеет точность до 10–15 миллисекунд, но не точно 1 миллисекунду.

То же самое относится и к счетчику производительности очереди. Есть ли другой способ получить точность с точностью до миллисекунды?

Ответы [ 3 ]

8 голосов
/ 29 июня 2010

Вы можете использовать этот класс DateTimePrecise , чтобы получить время высокой точности в .NET

ОБНОВЛЕНИЕ
Ссылка CodeProject больше не работает.Я взял код с archive.org и вставил его сюда для дальнейшего использования.Этот код включен здесь «как есть», точно так же, как он был включен на странице CodeProject.

DateTimePrecise так же легко использовать, как и DateTime.Now, за исключением того, что DateTimePrecise.Now является методом экземпляра, а не статическим методом, поэтому вы должны сначала создать экземпляр 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;
}
7 голосов
/ 29 июня 2010

Windows не хочет тратить электроэнергию, обновляя системные часы 1000 раз в секунду, поэтому по умолчанию обновляется только 60-100 раз в секунду. Если вы установите мультимедийный таймер на 1 мс, вы можете получить разрешение 1 мс на часах, но это не рекомендуется.

Для более подробной информации об экономии электроэнергии, то, что происходит, когда процессор некоторое время простаивает, может перейти в состояние с очень низким энергопотреблением. Всякий раз, когда он прерывается (например, для увеличения тактовых импульсов), он должен выходить из своего состояния с очень низким энергопотреблением и использовать большое количество электроэнергии для питания всего ЦП для обслуживания этого прерывания. Другими словами, дополнительная мощность заключается не в увеличении тактов, а в том, чтобы процессор не спал.

Поскольку мой ноутбук использует 10 Вт в режиме ожидания, когда тактовая частота составляет 60 Гц, и 11 Вт, когда он составляет 1000 Гц, а время работы от аккумулятора составляет 300 минут, то более медленные часы дают мне почти 30 дополнительных минут автономной работы!

6 голосов
/ 29 июня 2010

Попробуйте System.Diagnostics.Stopwatch для синхронизации с высоким разрешением.

Если установленное оборудование и операционная система поддерживают счетчик производительности с высоким разрешением, класс Stopwatch используетэтот счетчик для измерения прошедшего времени.В противном случае класс Секундомер использует системный таймер для измерения прошедшего времени.

Попробуйте собственный DateTime.Ticks для точности системного времени до ста наносекунд;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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...