简体   繁体   中英

System.Timers.Timer strange behaviour

Here is a code. Run and immediately keep P pressed. You should see the first date twice. I see. And I really don't know why it is so. I would like to understand it. Could someone explain it to me in clear way ?

using System;
using System.Timers;
using System.Diagnostics;

namespace Timer1
{
    class Program
    {
        static Stopwatch stopwatch = new Stopwatch();

        static Timer timer;

        static int interval = 1000;

        static void Main(string[] args)
        {
            Console.SetBufferSize(1000, 1000);

            timer = new Timer(interval);
            timer.Elapsed += Function;
            timer.Interval = interval;
            timer.Enabled = true;

            stopwatch.Start();

            while (true)
            {
                ConsoleKey key = Console.ReadKey(true).Key;

                if (key == ConsoleKey.P)
                {
                    int temp = interval - (int)stopwatch.ElapsedMilliseconds;

                    if (temp > 0)
                        timer.Interval = temp;

                    else
                        Function(null, null);
                }

                else
                {
                    timer.Dispose();
                    break;
                }

                Console.ReadKey(true);
            }
        }

        static public void Function(object sender, EventArgs e)
        {
            timer.Interval = interval;
            Console.WriteLine(DateTime.Now);
            stopwatch.Reset();
            stopwatch.Start();
        }
    }
}

The way your code is written, you have two paths to Function(). One path is when the timer actually elapses and the Function() is "handled" as a result. The other path is when

interval - stopwatch.ElapsedMilliseconds

is not greater than 0, in which case you call Function() directly.

It looks like you are using the System.Timers.Timer. This is run on a threadpool thread. Since you have multiple threads running, both can call Function(). You may think you guarded against that by resetting your internal and stopwatch in Function(), but the Console.WriteLine() is enough to allow one thread to defer and let the other thread run (and on multiprocessor computers, both threads can run at once on different processors).

By the nature of your logic, it is guaranteed that the timer interval will fire (call the handler) at nearly the same time that your interval test reaches 0, so you can expect it to run through both paths.

The example doesn't look very useful. Is it simply to understand timers? You can change the interval of the time if you like, but why bother when you are changing it to roughly what it was (or should be)?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM