System.Timers.Timer и Lock - C#

Узнай цену своей работы

Формулировка задачи:

Добрый день. Почитал немного про Thread Safety, про ThreadPool, про синхронизацию потоков. Но всё равно что-то не сходится, потому прошу пояснить, если возможно.

Вопрос:

Как именно работает System.Timers.Timer в плане создания потоков?

Сделал простой код. Нажимаю кнопку, запускаю таймер с интервалом 1 мс. Внутри выполняется функция ScreenCapture, которая (по результатам теста) выполняется где-то 15 мс. Как я думал, потоки будут перекрывать друг друга и нужна будет блокировка или какая-то другая синхронизация. Использовал lock, использовал Monitor.TryEnter (с разными значениями), использовал AutoReset = false. Удивительно, что в любом варианте вывод на экран был одинаковый с небольшими колебаниями ("15600 / 1000"). Получается, что следующий поток таймера всё-таки ждёт окончания предыдущего и никакие локи не нужны? На форумах нашёл очень много про блокировки в таймерах, везде советуют их использовать. Почему так получается?
        private void button1_Click(object sender, EventArgs e)
        {            
            test = 0;
 
            System.Timers.Timer test_timer = new System.Timers.Timer();
            test_timer.Interval = 1;
            test_timer.Elapsed += test_timer_Tick;
            //test_timer.AutoReset = false;
 
            sw = new Stopwatch();
            sw.Start();
            test_timer.Start();
        }
 
 public void test_timer_Tick(object sender, EventArgs eventArgs)
        {
                var timer = (System.Timers.Timer)sender;
                test++;
                ScreenCapture(cdr_run);
                if (test == 1000)
                {
                    timer.Stop();
                    MessageBox.Show(sw.ElapsedMilliseconds.ToString() + " / " + test.ToString());
                    sw.Reset();
                }
 
                //if (test < 1000) timer.Start();
        }

Решение задачи: «System.Timers.Timer и Lock»

textual
Листинг программы
        private static readonly Stopwatch TestStopwatch = new Stopwatch();
        private static int _counter;
 
        private void button1_Click(object sender, EventArgs e)
        {
            var timerTest = new System.Timers.Timer
            {
                AutoReset = false,
                Interval = 100
            };
            _counter = 0;
            timerTest.Elapsed += timerTest_Elapsed;
            timerTest.Enabled = true;
        }
 
 
        private static void timerTest_Elapsed(object sender, EventArgs e)
        {
            var timerTest = (System.Timers.Timer)sender;
            _counter++;
 
            try
            {
                if (!TestStopwatch.IsRunning) 
                    TestStopwatch.Start();
            }
            catch
            {
                //ignore
            }
            finally
            {
                if (_counter > 10)
                    MessageBox.Show(@"Времени прошло за " + (_counter - 1) + @" кругов по " + timerTest.Interval + @"мс: " + TestStopwatch.ElapsedMilliseconds);
                else
                {
                    TestStopwatch.Reset();
                    timerTest.Enabled = true;
                }
            }
        }

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

6   голосов , оценка 4 из 5