Best Timer approach in C# console batch application


Question

Which is the best timer approach for a C# console batch application that has to process as follows:

  1. Connect to datasources
  2. process batch until timeout occurs or processing complete. "Do something with datasources"
  3. stop console app gracefully.

related question: How do you add a timer to a C# console application

1
3
5/23/2017 12:07:11 PM

Accepted Answer

Sorry for this being an entire console app... but here's a complete console app that will get you started. Again, I appologize for so much code, but everyone else seems to be giving a "oh, all you have to do is do it" answer :)

using System;
using System.Collections.Generic;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static List<RunningProcess> runningProcesses = new List<RunningProcess>();

        static void Main(string[] args)
        {
            Console.WriteLine("Starting...");

            for (int i = 0; i < 100; i++)
            {
                DoSomethingOrTimeOut(30);
            }

            bool isSomethingRunning = false;

            do
            {
                foreach (RunningProcess proc in runningProcesses)
                {
                    // If this process is running...
                    if (proc.ProcessThread.ThreadState == ThreadState.Running)
                    {
                        isSomethingRunning = true;

                        // see if it needs to timeout...
                        if (DateTime.Now.Subtract(proc.StartTime).TotalSeconds > proc.TimeOutInSeconds)
                        {
                            proc.ProcessThread.Abort();
                        }
                    }
                }
            }
            while (isSomethingRunning);

            Console.WriteLine("Done!");    

            Console.ReadLine();
        }

        static void DoSomethingOrTimeOut(int timeout)
        {
            runningProcesses.Add(new RunningProcess
            {
                StartTime = DateTime.Now,
                TimeOutInSeconds = timeout,
                ProcessThread = new Thread(new ThreadStart(delegate
                  {
                      // do task here...
                  })),
            });

            runningProcesses[runningProcesses.Count - 1].ProcessThread.Start();
        }
    }

    class RunningProcess
    {
        public int TimeOutInSeconds { get; set; }

        public DateTime StartTime { get; set; }

        public Thread ProcessThread { get; set; }
    }
}
4
11/28/2008 11:47:41 AM

It depends on how accurate do you want your stopping time to be. If your tasks in the batch are reasonably quick and you don't need to be very accurate, then I would try to make it single threaded:

DateTime runUntil = DataTime.Now.Add(timeout);
forech(Task task in tasks)
{
   if(DateTime.Now >= runUntil)
   {
        throw new MyException("Timeout");
   }
   Process(task);
}

Otherwise you need to go mulithreaded, which is always more difficult, because you need to figure out how to terminate your task in the middle without causing side effects. You could use the Timer from System.Timers: http://msdn.microsoft.com/en-us/library/system.timers.timer(VS.71).aspx or Thread.Sleep. When the time-out event occurs you can terminate the thread that does the actual processing, clean up and end the process.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon