Search code examples
c#timerscheduled-tasksmessage-loop

Application.Run(), Application.Exit() and timers


I have a winforms application that I will be calling through the task scheduler to download files and insert them to a database. However it is unpredictable when the files are available so I have used timer (System.Windws.Forms.Timer) to poll for the files.

 static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            if (args != null && args.Length > 0)
            {

                Form1 f1 = new Form1();
                if (f1.IsLive)
                {
                    f1.OnLaunch(); // tests DB connection and reads and updates the expiry date list.

                    if (args[0] == "FullStats")
                        f1.FullStatsDataPump();
                    else if (args[0] == "OptionsStats")
                    {
                        f1.OptionsStatsTimer_Tick(null, null);
                        f1.OptionsStatsTimer.Start();
                    }
                    else if (args[0] == "OptionsTraded")
                    {
                        f1._optionsTradedTimer_Tick(null, null);
                        f1.OptionsTradedTimer.Start();
                    }
                    else
                    {
                        EmailManager.InvalidInputArgument(args[0]);
                        Application.Exit();
                    }

                    Application.Run();
                }

            }

In the above code snippet, OptionsTradedTimer / OptionsStatsTimer both poll for files and then begin processes that end with Application.Exit(). This runs perfectly but then afterwards it gets stuck in an infinite message loop. I thought that Application.Run() would be called immediately after the first timer ticks and thus when Application.Exit() eventually gets called it would end the message loop. But if I step through the code then after that Application.Exit() the program returns to the timer.tick() where it originated and then continues on to the Application.Run() at the bottom. The Application.Run() at the bottom is necessary as without it the timers will only tick once and then the app will exit.

So how do I correctly tell the application to exit? Or where should I be calling Application.Run()?


Solution

  • Can't delete the question so might as well answer it.

    The problem only occurs if the timer reaches the Application.Exit() line the first time it runs. (i.e. if the file is available already when the program is run). In this case Application.Exit() is called before Application.Run() where as if the timer doesn't reach the Application.Exit() on its first run (i.e. file is not yet available) then Application.Run() gets called and Application.Exit() only gets called later.

    So to solve this I just added a condition in the timers' tick methods to make sure they don't so anything on their first run.

    I don't agree with restructuring the program as the way it stands I can run it through the task scheduler to download the files daily without a form and with the polling functionality and I can also run it through VS as a normal winforms app with buttons for testing, debugging and downloading files when something went wrong.