-1

I am calling two timers in one WinForm for different processes, both are using the same try-catch format. It works fine for the first few days, then starts to become slow. I can see some load on the server. Is my timer event correct? Is this event not putting much load?

In my try-catch, I only stop the timer if my code catches any exception. I doubt if not exception, and my time is not stopped. If I start the timer the second time, it will put more load or its just reset. Please give your valuable advice. Thanks a bunch in advance.

My code is below.

Timer 1 Tick:

private void timerMain_Tick(object sender, EventArgs e)
{
    try
    {
        // Retrieve some status and Update
    }
    catch (Exception ex)
    {
        timerMain.Stop();
        MessageBoxHelper.ShowException(LanguagePack.LanguageHelper.GetString(GlobalParameters.Language, "Error_ExecutionEx"), ex);
    }
    finally
    {
        timerMain.Start();
    }
}

Timer 2 Tick:

private void timerWorkStep_Tick(object sender, EventArgs e)
{
    try
    { 
        // Retreive Some value from web proxy and set to label
    }
    catch (Exception ex)
    {
        timerWorkStep.Stop();
        MessageBoxHelper.ShowException(LanguagePack.LanguageHelper.GetString(GlobalParameters.Language, "Error_ExecutionEx"), ex);
    }
    finally
    {
        timerWorkStep.Start();
    }
}
ninja coder
  • 1,067
  • 9
  • 22
Mdyahiya
  • 167
  • 3
  • 15
  • It doesn't appear anything is wrong in the timer setup. It's possible that any memory leak that may be occurring existing in whatever you are doing in the try portion of your code. What has made you think the timer is the issue? – ninja coder Sep 19 '17 at 15:17
  • Thanks for your comment. In my event, I called finally timer.start even though i dont stop the timer except the exception. so i felt, it may be over loop and timer will be running multiple instance. – Mdyahiya Sep 19 '17 at 15:44
  • If you want the person you're replying to to be notified, you have to mention them like so: @ninjacoder – s.m. Sep 19 '17 at 15:51
  • @ninjacoder Sorry, next time I will make sure I will follow in my reply. – Mdyahiya Sep 20 '17 at 01:50

1 Answers1

1

I missed the problem but it was pointed out to me in the comments by the OP so here is my answer.

I wouldn't say you have exactly a memory leak because you are eventually releasing the memory and resources you are using, but as you pointed out in the comment, I would definitely agree that only stopping your timer in the catch and always starting it in the finally could certainly cause your tick to run more often that on a fixed interval. If you run the example below you will see what I mean.

Timer Running Many Ticks At Once Example

void Main()
{
    _timer = new System.Timers.Timer(100);

    _timer.Elapsed += Timer_Elapsed;

    _timer.Start();
}

private void Timer_Elapsed(object sender, EventArgs e)
{
    try
    {
        for (int i = 0; i < 15; i++)
        {
            Console.Write(i + " ");
            Thread.Sleep(10);
        }
        Console.WriteLine();
    }
    catch (Exception ex)
    {
        _timer.Stop();
        Console.WriteLine(ex.Message);
    }
    finally
    {
        _timer.Start();
    }
}

private System.Timers.Timer _timer;

I use timers on a regular basis for most of my windows services and we have adopted the pattern of stopping the timer as the first thing in the tick and restarting it once the tick has finished. The problem with the code directly below it that it will not run every defined interval because of the time it takes to actually process

Timer Pattern

private void Timer_Elapsed(object sender, EventArgs e)
{
    try
    {
        _timer.Stop();

        //some work
    }
    catch(Exception ex)
    {

    }
    finally
    {
        _timer.Start();
    }
}

If you want more of a reliable run every hour at 5 after the hour, you will need to do something like this:

Timer Pattern on Reliable Interval

public class NextRunCalculator
{
    public double CalculateTimeUntilNextRun()
    {
        List<int> processingMinutes = new List<int> { ServiceConstants.RunMinute5 };//this is a list of minutes during the hour you want the service to run

        int t = int.MaxValue;
        foreach (var processingMinute in processingMinutes)
        {
            var minutesRemaining = processingMinute - DateTime.Now.Minute;

            if (minutesRemaining <= 0)
            {
                minutesRemaining = 60 + minutesRemaining;//change 60 to however often you want the timer to run
            }

            if (minutesRemaining < t)
            {
                t = minutesRemaining;
            }
        }

        return TimeSpan.FromMinutes(t).TotalMilliseconds;
    }
}

private void Timer_Elapsed(object sender, ElapsedEventArgs e)
{
    _timer.Stop();

    //do work

    _timer.Interval = _nextRunCalculator.CalculateTimeUntilNextRun();
    _timer.Start();
}
ninja coder
  • 1,067
  • 9
  • 22
  • Thanks for the feedback. Even myself thought same and set enable false at the start of my code and set true at finally to give a try, I will monitor the performance next few days and will update you. Note: My timer has to run continuously when the form is active and set the interval 15 seconds. Hope will perform better. Once again thanks for the detail answer. – Mdyahiya Sep 22 '17 at 13:41