0

I am unable to trace the cause of the problem here. The program starts a service that runs continuously. While this runs I need to run another piece of code every 30 seconds that I can do it either by using a background worker or using a timer.

I tried using both timer and async background worker. However every time there is a callback after 30 seconds the program exits. The code is given below,

using log4net;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "logger.xml", Watch = true)]

namespace Service.Envelope
{
    static class Program
    {
        private static readonly System.Timers.Timer Timer;
        private static readonly ILog LOGGER = LogManager.GetLogger(typeof(Program));
        private static Dictionary<int, int[]> MainCpseIdNodeIdDict = new Dictionary<int, int[]>();
        private static int[] NodeIds;
        private static int[] MainCpseIds;
        private static EnvelopeMainService envelopeMainService;

        private static void InitializeDict()
        {
            MainCpseIdNodeIdDict.Add(7, new int[] { 23476, 2276, 23472, 24498 });
            //MainCpseIdNodeIdDict.Add(9, new int[] { 23476, 2276, 23472, 24498 });
            MainCpseIds = new List<int>(MainCpseIdNodeIdDict.Keys).ToArray();
            NodeIds = new List<int>(MainCpseIdNodeIdDict.Values.SelectMany(x => x)).ToArray();
        }

        private static void StartBackgroundWorker()
        {
            LOGGER.Fatal("Starting bg worker..");
            BackgroundWorker work = new BackgroundWorker();
            work.DoWork += new DoWorkEventHandler(work_DoWork);
            work.RunWorkerAsync();
        }


        private static void work_DoWork(object sender, DoWorkEventArgs e)
        {
            while (true)
            {
                System.Threading.Thread.Sleep(30 * 1000);
                EnvelopeMainService.EnvelopeSwitch(false);
                Console.WriteLine("Generating data ..");
                envelopeMainService.GenerateBaseDataForGoodPart(); // program exits here
                System.Threading.Thread.Sleep(30 * 1000);  
            }
        }

        static void Main()
        {
            InitializeDict();
            LOGGER.MBLog("Start LOGGING");
            StartBackgroundWorker();
            EnvelopeMainService.SetUpTables();
            EnvelopeMainService envelopeMainService = new EnvelopeMainService(NodeIds, MainCpseIds);
            envelopeMainService.InitiateLiveEnvelope(MainCpseIdNodeIdDict);
        }
    }
}

The program exits at envelopeMainService.GenerateBaseDataForGoodPart(). This function calls a SQL function that loads the data to a datatable.

The timer version is given below. In both the versions the program exits at the same spot.

using log4net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Timers;
using System.Xml;

[assembly: log4net.Config.XmlConfigurator(ConfigFile = "logger.xml", Watch = true)]

namespace Service.Envelope
{
    static class Program
    {
        private static System.Timers.Timer Timer;
        private static readonly ILog LOGGER = LogManager.GetLogger(typeof(Program));
        private static Dictionary<int, int[]> MainCpseIdNodeIdDict = new Dictionary<int, int[]>();
        private static int[] NodeIds;
        private static int[] MainCpseIds;
        private static EnvelopeMainService envelopeMainService;

        private static void TimeIt()
        {
            Timer = new System.Timers.Timer(30000);
            Timer.AutoReset = false;
            Timer.Elapsed += OnTimedEvent;
            Timer.Start();
        }

        private static void InitializeDict()
        {
            MainCpseIdNodeIdDict.Add(7, new int[] { 23476, 2276, 23472, 24498 2276 });  
            MainCpseIds = new List<int>(MainCpseIdNodeIdDict.Keys).ToArray();
            NodeIds = new List<int>(MainCpseIdNodeIdDict.Values.SelectMany(x => x)).ToArray();
        }

        private static void StartService()
        {
            EnvelopeMainService.SetUpTables();
            envelopeMainService = new EnvelopeMainService(NodeIds, MainCpseIds);
            envelopeMainService.InitiateLiveEnvelope(MainCpseIdNodeIdDict);            
        }

        static void Main()
        {
            TimeIt();
            InitializeDict();
            LOGGER.MBLog("Start LOGGING");
            StartService();
        }

        private static void OnTimedEvent(object source, ElapsedEventArgs e)
        {
            Timer.Enabled = false;
            Timer.Stop();
            EnvelopeMainService.EnvelopeSwitch(false);            
            Console.WriteLine("Generating data ..");
            envelopeMainService.GenerateBaseDataForGoodPart(); // program exits here
            Console.WriteLine($"Data generated\n Starting live envelope");
            EnvelopeMainService.EnvelopeSwitch(true);
            Timer.Enabled = true;
            Timer.Start();                   
        }
    }
}

Murtaza
  • 413
  • 1
  • 3
  • 13
  • You need to `await`. Use an `async Task Main` method. – Dai Mar 12 '22 at 11:25
  • The `BackgroundWorker` is a [technologically obsolete](https://stackoverflow.com/questions/12414601/async-await-vs-backgroundworker/64620920#64620920) class IMHO. Regarding the timer stopping, take a look at this: [Can Timers get automatically garbage collected?](https://stackoverflow.com/questions/18136735/can-timers-get-automatically-garbage-collected) – Theodor Zoulias Mar 12 '22 at 11:41
  • 1
    In the first code listing you don’t wait for the BackgroundWorker to complete. That’s kinda like the equivalent for a contemporary fire and forget Task. –  Mar 12 '22 at 11:49
  • `EnvelopeMainService envelopeMainService = new EnvelopeMainService(...)` in your Main function creates a local variable `envelopeMainService`; the field with the same name is never inistialized ans therefore any use of it results in a NukkReferenceException. – Klaus Gütter Mar 13 '22 at 06:58

0 Answers0