2009-10-26 80 views
0

我有一个小的代码示例:Stack.Overflow错误 - WinForms应用程序比。 WINSERVICE

private void MonitorItems() 
     { 
      if (someCondition) 
      { 
       dateSelected = DateTime.Now; 
       GetAllItems(); 
      } 
      else 
      { 
       if(allItems.Count>0) 
        CheckAllItems(); 
      } 
      MonitorItems(); 
     } 

的方法GetAllItems进入数据库,并获得集合中的所有新项目 - > allItems。 然后,CheckAllItems方法:

private void CheckAllItems() 
     { 
      foreach (Item a in new List<Item>(allItems)) 
      { 
       switch (a.Status) 
       { 
        case 1: 
         HandleStatus1(); 
         break; 
        case 2: 
         HandleStatus2(a); 
         break; 
        case 0: 
         HandleStatus0(a); 
         break; 
        default: 
         break; 
       } 
      } 
     } 

在某些情况下(在HandleStatus1和HandleStatus2)我需要去DB,做一些更新,然后再次调用该方法GetAllItems填充集合allItems。

这种类型的代码在WinFormsApp中抛出Stack.Overflow异常。 我有两个问题:
1.是否会在WinService应用程序中使用相同的代码抛出此类异常?
2.您对使用计时器而不是自我调用方法有何看法?

回答

1

“自我调用方法”更正确地称为"recursive method"。你的解决方案很有创意,我会给你。但不要这样做。堆栈空间非常有限。当你转向服务时,你会看到这个问题,并且有更好的方法来处理这个问题。计时器在服务中使用时非常合适。

+0

第一次实施计划与计时器。但我有一个问题。计时器在1秒内设置为“滴答”。如果CheckAllItems()中的工作未完成并且计时器再次打勾,会发生什么情况?关于代码的一点说明:必须有递归调用,以便监控不会停止。 – ZokiManas 2009-10-27 07:07:47

+1

@ZM:如果使用System.Timers.Timer类,并且在前一个事件处理完成之前计时器再次打勾,则会在另一个线程上再次调用您的处理程序。确保你的代码可以处理(换句话说,确保你的代码是可重入的)。如果你不想要这种行为,你可以在处理程序中停止()定时器,然后在完成时再次启动()。 – 2009-10-27 15:19:43

+0

@ZM:如果以前不清楚,递归调用不只是一个坏主意,它们是一个非常糟糕的主意。不要这样做。 – 2009-10-27 15:20:32

1

在你的情况下递归调用方法是不好使用作为使用计时器来做到这一点。你既不应该做!

只需使用一个简单的循环,然后发送线程休眠一段时间。

+0

@Foxfire:计时器出了什么问题? – 2009-10-26 22:11:48

+0

+1定时器不是好选择 – 2009-10-26 22:12:49

+0

如果正确使用,没有任何问题。但是,如果他创建这样的代码,我担心他会在错误的地方创建计时器,这可能会导致递归(事实上很难找到)。 – Foxfire 2009-10-26 22:15:31

0

MS IL具有.tail操作码。 ((

0

为什么你需要递归呢?没有流控制语句可以让方法停下来,但是c#点想要识别尾递归(顺便说一句,尾递归在.net中很慢) 。递归并退出链中的无限递归可能是什么原因造成的溢出更好的解决方案,以彻底废除递归删除其他包装完成相同的结果,而不必改乘:

private void MonitorItems() 
{ 
    if(someCondition) 
    { 
     dateSelected = DateTime.Now; 
     GetAllItems(); 
    } 
    if(allItems.Count>0) 
     CheckAllItems(); 
} 

这可以在不陷入循环的情况下实现相同的结果然后您可以实现规则以在执行环境的上下文中重复调用:在服务应用程序上单击表单或计时器上的按钮离子。