2017-08-25 29 views
-1

我想处理异常,但它不起作用! 最新的问题?如何处理System.Threading.Timer中的异常

让我们说在Main中我使用任何参数运行SetUpTimer。

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."); 
    } 
} 

所以现在如果我执行它会抛出一个异常与报告名称A,D,F。但它不会抓住它,但为什么?我能做些什么呢?

+1

您是尝试/捕获仅创建计时器,操作的不执行。你可以把所有的代码放在try/catch中的Action“RunReportTask”中,或者你可以在你的应用中注册一个[uncaughtExceptionHandler](https://csharp.2000things.com/tag/unhandled-exceptions/)。 – Fildor

+0

将try/catch放在抛出异常的同一个方法中是没有意义的,但这就是所有可以用你发布的代码完成的方法。据推测,随着更多的信息,它将清楚你如何处理错误,但这些信息不在这里,所以这个问题有太多可能的答案。 –

回答

0

Timer在单独的ThreadPool线程上调用TimerCallback。 在TimerCallback方法中引发的异常不会传播到创建定时器的代码/线程(它们只是'失望')。 如果你想在你的回调方法之外处理它们:你应该在回调方法中捕获它们并使用一些机制在原始线程中重新抛出或处理它们。 我个人喜欢这个IProgress

有许多在原始代码的语法错误,而是基于对下面的例子应该工作:

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); 
     } 
    } 

警告:除了语法,还有与代码中的一个重要问题你例。只要您希望将其激活,就必须保留对Timer实例的引用。只要Timer超出范围,它就成为垃圾收集的候选对象。 在你的例子中,Timer是一个局部变量,只要方法结​​束,它就会超出范围。如果在alertTime之前收集垃圾,将永远不会调用TimerCallback。出于这个原因,我已将您的Timer晋升到您班级的私人领域。

此外,当你不再需要Timer,你应该叫Dispose()Timer释放其资源(例如,在Dispose梅索德为你的类)。

+0

谢谢,是的,我知道语法是坏的,但我很急(:(。我明天会检查这个例子,然后再给你检查:)再次感谢 – Amsel

0

试试这个(因为你没有在try块未关闭括号):

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....") 
    } 
}