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 Timer
is 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 Timer
to 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).