Интервалы System.Threading.Timer для точных трехминутных значений - PullRequest
0 голосов
/ 14 марта 2012

Я использую System.Threading.Timer для получения точных трехминутных интервалов:

private System.Threading.Timer ReadTimer;
        private System.Threading.TimerCallback ReadTimerCallback;
        public Form1()
        {
            InitializeComponent();
        }

        #region Working with RichTextBox and system event log for logging
        public enum LogStyle
        {
            InformationStyle = 0,
            WarningStyle = 1,
            ErrorStyle = 3
        }
        private delegate void LogTextDelegate(LogStyle logStyle, string message);
        private int NewLinesCount(string Message)
        {
            string[] strings = { Environment.NewLine };
            return Message.Split(strings, StringSplitOptions.RemoveEmptyEntries).Count();
        }
        private void AddText(LogStyle logStyle, string message)
        {
            LogBox.Select(0, 0);
            string TextToAppend = DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff") + " " + message + Environment.NewLine;
            LogBox.AppendText(TextToAppend);
            LogBox.Select(LogBox.TextLength - TextToAppend.Length + NewLinesCount(TextToAppend), TextToAppend.Length);
            switch (logStyle)
            {
                case LogStyle.InformationStyle:
                    {
                        EventLog.WriteEntry(Process.GetCurrentProcess().ProcessName, TextToAppend, EventLogEntryType.Information);
                        LogBox.SelectionColor = Color.Green;
                        LogBox.Select(LogBox.TextLength, LogBox.TextLength);
                        break;
                    }
                case LogStyle.WarningStyle:
                    {
                        EventLog.WriteEntry(Process.GetCurrentProcess().ProcessName, TextToAppend, EventLogEntryType.Warning);
                        LogBox.SelectionColor = Color.DarkOrange;
                        LogBox.Select(LogBox.TextLength, LogBox.TextLength);
                        break;
                    }
                case LogStyle.ErrorStyle:
                    {
                        EventLog.WriteEntry(Process.GetCurrentProcess().ProcessName, TextToAppend, EventLogEntryType.Error);
                        LogBox.SelectionColor = Color.Red;
                        LogBox.Select(LogBox.TextLength, LogBox.TextLength);
                        break;
                    }
            }
        }
        public void LogText(LogStyle logStyle, string Message)
        {
            if (LogBox.InvokeRequired)
            {
                LogBox.Invoke(new LogTextDelegate(this.AddText), new object[] { logStyle, Message });
            }
            else
            {
                AddText(logStyle, Message);
            }
        }
        #endregion

        private void button1_Click(object sender, EventArgs e)
        {
            LogText(LogStyle.WarningStyle, "Current thread ID = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
            LogText(LogStyle.WarningStyle, "Threads count = " + System.Diagnostics.Process.GetCurrentProcess().Threads.Count);
            AutoResetEvent ReadautoEvent = new AutoResetEvent(false);
            ReadTimerCallback = new TimerCallback(this.ShowText);
            ReadTimer = new System.Threading.Timer(ReadTimerCallback, ReadautoEvent, (long)(CurrentTime.AddMinutes(3) - DateTime.Now).TotalMilliseconds, 180000);

        }

        public void ShowText(object Object)
        {
            ReadTimer.Change((long)(CurrentTime.AddMinutes(3) - DateTime.Now).TotalMilliseconds, 180000);
            LogText(LogStyle.WarningStyle, "Now is " + DateTime.Now.ToString("dd.MM.yyyy HH:mm:ss.fff"));
            LogText(LogStyle.WarningStyle, "Now is " + "Current thread ID = " + System.Threading.Thread.CurrentThread.ManagedThreadId);
            LogText(LogStyle.WarningStyle, "Threads count = " + System.Diagnostics.Process.GetCurrentProcess().Threads.Count);
        }

        private DateTime CurrentTime
        {
            get
            {

                DateTime now = DateTime.Now;
                DateTime val;
                val = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0)
                     .AddMinutes(((now.Minute) / 3) * 3 - now.Minute);
                return val;
            }
        }

Но иногда я вижу следующее:

14.03.2012 09:20:33.264 Current thread ID = 10
14.03.2012 09:20:33.361 Threads count = 13
14.03.2012 09:20:59.985 Now is 14.03.2012 09:20:59.977
14.03.2012 09:20:59.991 Now is Current thread ID = 12
14.03.2012 09:20:59.997 Threads count = 15
14.03.2012 09:21:00.010 Now is 14.03.2012 09:21:00.009
14.03.2012 09:21:00.019 Now is Current thread ID = 12
14.03.2012 09:21:00.025 Threads count = 17
14.03.2012 09:24:00.252 Now is 14.03.2012 09:24:00.252
14.03.2012 09:24:00.260 Now is Current thread ID = 8
14.03.2012 09:24:00.268 Threads count = 17
14.03.2012 09:27:00.331 Now is 14.03.2012 09:27:00.330
14.03.2012 09:27:00.337 Now is Current thread ID = 6
14.03.2012 09:27:00.343 Threads count = 14
14.03.2012 09:30:00.021 Now is 14.03.2012 09:30:00.021
14.03.2012 09:30:00.027 Now is Current thread ID = 8
14.03.2012 09:30:00.033 Threads count = 13
14.03.2012 09:32:59.962 Now is 14.03.2012 09:32:59.961
14.03.2012 09:32:59.968 Now is Current thread ID = 6
14.03.2012 09:32:59.974 Threads count = 13
14.03.2012 09:33:00.013 Now is 14.03.2012 09:33:00.013
14.03.2012 09:33:00.020 Now is Current thread ID = 6
14.03.2012 09:33:00.026 Threads count = 14
14.03.2012 09:35:59.891 Now is 14.03.2012 09:35:59.891
14.03.2012 09:35:59.898 Now is Current thread ID = 8
14.03.2012 09:35:59.904 Threads count = 13
14.03.2012 09:36:00.001 Now is 14.03.2012 09:35:59.999
14.03.2012 09:36:00.008 Now is 14.03.2012 09:36:00.004
14.03.2012 09:36:00.015 Now is Current thread ID = 8
14.03.2012 09:36:00.021 Now is Current thread ID = 6
14.03.2012 09:36:00.030 Threads count = 14
14.03.2012 09:36:00.035 Threads count = 14

Почему это выполняется дважды за три минуты: в 14.03.2012 09: 20: 59.985 и 14.03.2012 09: 21: 00.010?

Где я должен это исправить?

В CurrentTime Я должен добавить 30 секунд, таких

DateTime now = DateTime.Now.AddSeconds(30) или как?

1 Ответ

2 голосов
/ 14 марта 2012

Здесь есть несколько вопросов.Самое большое, что я вижу, это ваша CurrentTime собственность:

DateTime now = DateTime.Now;
DateTime val;
val = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 0)
                 .AddMinutes(((now.Minute) / 3) * 3 - now.Minute);
return val;

Посмотрите, что происходит, когда now.Minute равно 59, 59/3 = 19, потому что это int.Остальная часть вашего выражения 59/3 * 3 - 59 приводит к -2.Вы эффективно перемотали таймер на две минуты назад. Однако , поскольку вы обнулили секунды при создании val, вы действительно установили таймер на 3 минуты назад.59 - не уникальный случай, но я извлекаю его из вашего набора данных.Код, который использует ваш CurrentTime, добавляет 3 минуты.Таким образом, вы в значительной степени говорите коду, чтобы он срабатывал немедленно.Причина, по которой вы видите, что он вызывается дважды, заключается в том, что эта строка в ShowText:

`ReadTimer.Change((long)(CurrentTime.AddMinutes(3) - DateTime.Now).TotalMilliseconds, 180000);` 

Когда ваш делегат обрабатывает таймер, событие немедленно возникает снова, потому что now.Minute по-прежнему 59,в результате чего ваш общий расчет CurrentTime будет на 3 минуты меньше, чем DateTime.Now.

Если все, что вы хотите сделать, - это запускать задачу каждые три минуты, то вам нужно следующее:

ReadTimer = new System.Threading.Timer(ReadTimerCallback, ReadautoEvent, 0, 180000);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...