0

I'm trying to handle exception but it doesn't work! whats the problem?

lets say in Main i run SetUpTimer with any parameters.

private void SetUpTimer(TimeSpan alertTime, string name) 
{

  DateTime current = DateTime.Now;
  TimeSpan timeToGo = alertTime - current.TimeOfDay;
  try
  {
    Timer timer = new Timer(x => RunReportTask(name),null, timeToGo, Timeout.InfiniteTimeSpan));

  catch(Exception e)
  { 
    Console.WriteLine("Log Exception....")
  }
}

private void RunReportTask(string name)
{

  Console.WriteLine("\r\n\r\nSTART Task \t\tReport: " + name);

  //DELAY 25 sec
  Task.Delay(25000);

  if (name.Equals("Report A") || name.Equals("Report D") || name.Equals("Report F"))
  {
    throw new Exception("Task failed!!!");
  }
  else
  {
    Console.WriteLine("Task: \t\t" + name + "\tDONE.");
  }
}

so now if i execute it will throw an exception with Report name A,D,F. but it won't catch it, but why? and what can i do about it?

imsome1
  • 1,182
  • 4
  • 22
  • 37
Amsel
  • 107
  • 1
  • 13
  • 1
    You are try/catching only the creation of the timer, not the execution of the Action. You could enclose all the code in the Action "RunReportTask" in a try/catch or you could Register an [uncaughtExceptionHandler](https://csharp.2000things.com/tag/unhandled-exceptions/) in your app. – Fildor Aug 25 '17 at 14:07
  • It would make very little sense to put a try/catch in the same method where the exception is thrown, but that's about all that could be done with the code you posted. Presumably, with more information, it would be clear how you want errors to be handled, but that information isn't here, so there are far too many possible answers to this question. – Peter Duniho Aug 28 '17 at 05:08

2 Answers2

2

The Timer calls the TimerCallback on a separate ThreadPool thread. Exceptions thrown in a TimerCallback method are not propagated to the code/thread where the timer was created (they just 'disapppear'). If you want to handle them outside of your callback method: you should catch them in the callback method and use some mechanism to rethrow or handle them in the original thread. Personally I like the IProgress for this.

There are a number of syntax errors in your original code, but based on that the following example should work:

 private Timer timer;

 public void SetUpTimer(DateTime alertTime, string name)
 {

      var progress = new Progress<Exception>((e) =>
                  {
                        // handle exception form timercallback here, or just rethrow it...
                        throw e;
                   });   

        DateTime current = DateTime.Now;
        TimeSpan timeToGo = (alertTime - current);
        timer = new Timer(x => RunReportTask(name, progress),
                 null, timeToGo, Timeout.InfiniteTimeSpan);
    }

    private void RunReportTask(string name, IProgress<Exception> progress)
    {

        try
        {

            Console.WriteLine("\r\n\r\nSTART Task \t\tReport: " + name);

            //DELAY 25 sec
            Task.Delay(25000);

            if(name.Equals("Report A") || name.Equals("Report D") || name.Equals("Report F"))
            {
                throw new Exception("Task failed!!!");
            }
            else
            {
                Console.WriteLine("Task: \t\t" + name + "\tDONE.");
            }
        }
        catch(Exception e)
        {
            progress.Report(e);
        }
    }

Warning: Apart from the syntax, there is an important issue with the code in your example. You have to keep a reference to your Timer instance for as long as you want to have it active. Whenever a Timer goes out of scope, it becomes a candidate for garbage collection. In your example the Timeris a local variable which goes out of scope as soon as the method finishes. If it is garbage collected before alertTime, the TimerCallback will never be called. For that reason i have promoted your Timerto a private field of your class.

Furthermore, when you no longer need the Timer, you should call Dispose() on the Timer to release its resources (e.g. in a Dispose methode for your class).

Johan Donne
  • 3,104
  • 14
  • 21
  • thanks, yes i know syntax is bad but i was in a hurry :(. i will check the example out tomorrow and give you the check then :) thanks again – Amsel Aug 25 '17 at 14:58
0

Try this one (because you did not close brackets in try block):

private void SetUpTimer(TimeSpan alertTime, string name) 
{

  DateTime current = DateTime.Now;
  TimeSpan timeToGo = alertTime - current.TimeOfDay;
  try
  {
    Timer timer = new Timer(x => RunReportTask(name),null, timeToGo, Timeout.InfiniteTimeSpan));
  }
  catch(Exception e)
  { 
    Console.WriteLine("Log Exception....")
  }
}
imsome1
  • 1,182
  • 4
  • 22
  • 37