Сравнение дат в таймере - PullRequest
1 голос
/ 11 апреля 2011

У меня есть таймер, который запускается каждую секунду, код ниже:

    public MainWindow()
    {
        InitializeComponent();

        DispatcherTimer timer = new DispatcherTimer();
        timer.Interval = TimeSpan.FromMilliseconds(1000);
        timer.Tick += new EventHandler(someEventHandler);
        timer.Start();
    }

    private void someEventHandler(Object sender, EventArgs args)
    {
        TVMonitor TVMonitor = new TVMonitor();
        if (TVMonitor.NeedsTurningOn())
        {
            Console.WriteLine("on");
            TVCOM.SendCommand(SettingManager.GetTVCode("on") + Environment.NewLine);
        }
    }

В функции NeedsTurningOn() У меня есть следующее:

    public bool NeedsTurningOn()
    {
        var turnon = (from settings in context.SystemSettings
                      where settings.SystemSettingName == "TVOnTime"
                      select settings).First();
        if (turnon.SystemSettingValue == String.Empty)
        {
            return false;
        }

        DateTime date = Convert.ToDateTime(turnon.SystemSettingValue);
        Console.WriteLine("Turnontime: " + date);
        Console.WriteLine("currenttim: " + DateTime.Now);
        if (date != DateTime.Now)
        {
            Console.WriteLine("false");
            return false;
        }
        else
        {
            Console.WriteLine("true");
            return true;
        }
    }

Теперь в консоликоторый я использую для отладки, у меня есть следующий вывод:

...
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:07
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:08
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:09
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:10
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:11
false
Turnontime: 11/04/2011 14:05:10
currenttim: 11/04/2011 14:05:12
false
...

Почему это все еще вызывает ложь вместо истины, если дата совпадает?

Ответы [ 7 ]

2 голосов
/ 11 апреля 2011

Дело в том, что переменная DateTime имеет разрешение 1 миллисекунда ... вы сравниваете ее с разрешением 1 секунда.

Попытка:

if (Math.Abs(date.Subtract(DateTime.Now).Milliseconds) < 1000) { ... }

Вы можете настроить разрешение совпадения, изменив 1000 на другое число ... 500 проверит, находится ли date в пределах полсекунды от текущей даты / времени.

1 голос
/ 11 апреля 2011

Другие ответы здесь указывают на то, почему вы видите свое поведение; а именно, что миллисекунды двух переменных DateTime различны.

Я бы порекомендовал вам сделать ваше состояние более гибким. Вы полагаетесь на тот факт, что ваш метод NeedsTurningOn будет выполняться в течение именно той секунды, которую вы настроили в настройке времени включения. Что если система зависнет на секунду? Ваш код может периодически пропустить окно для включения. Что если вы решите изменить интервал таймера с 1000 до 5000? В этом случае ваш код будет иметь только около 1/5 шанса выполнения в течение правильной секунды.

Я бы предложил сделать ваше состояние примерно таким:

    if (this.IsTurnedOn)
    {
        Console.WriteLine("false - already on");
        return false;
    }
    else
    {
        DateTime date = Convert.ToDateTime(turnon.SystemSettingValue);
        Console.WriteLine("Turnontime: " + date);
        Console.WriteLine("currenttim: " + DateTime.Now);
        if (date > DateTime.Now)
        {
            Console.WriteLine("false");
            return false;
        }
        else
        {
            Console.WriteLine("true");
            return true;
        }
    }

По сути, добавьте свойство IsTurnedOn в свой класс TVMonitor, чтобы действовать как флаг, чтобы вы знали, действительно ли вам нужно его включить. Кроме того, измените date != DateTime.Now на date > DateTime.Now, потому что я предполагаю, что вы действительно пытаетесь определить, что настроенное время включения истекло.

1 голос
/ 11 апреля 2011

Вы сравниваете только времена каждую секунду - миллисекунды все равно будут отличаться (особенно если принять во внимание, что время включения, которое вы сравниваете, скорее всего, не использует миллисекунды). Для сравнения во втором разрешении вы можете сделать что-то вроде этого:

DateTime currentTime = DateTime.Now;
currentTime = currentTime.AddMilliseconds(-currentTime.Millisecond);
0 голосов
/ 11 апреля 2011

Решение моей проблемы:

Спасибо за всю вышеупомянутую помощь, я добавил это в свою функцию до сравнения дат:

DateTime date = Convert.ToDateTime(turnon.SystemSettingValue);
DateTime current = DateTime.Now;
current = current.AddMilliseconds(-current.Millisecond);
date = date.AddMilliseconds(-date.Millisecond);
0 голосов
/ 11 апреля 2011

Поскольку Date и TimeSpan содержат компоненты меньше секунд, то есть миллисекунд и тиков.

Я бы предложил сравнить свойство TotalSeconds.

0 голосов
/ 11 апреля 2011

Попробуйте записать свое время как date.Ticks и DateTime.Now.Ticks, и вы поймете, почему. Разрешение намного меньше секунды.

Если вам нужно второе разрешение, сравните только день, месяц, год, час, минуту и ​​секунду.

A один тик представляет сто наносекунд или одну десятую миллионную секунды. В миллисекунде 10 000 тиков, поэтому вам понадобится действительно быстрый компьютер, чтобы соответствовать одному и тому же тику:)

0 голосов
/ 11 апреля 2011

Может быть, вам стоит сравнить общее количество секунд или что-то в этом роде? Я могу представить, что миллисекунды отличаются ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...