2009-10-26 83 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(); 
} 

這可以在不陷入循環的情況下實現相同的結果然後您可以實現規則以在執行環境的上下文中重複調用:在服務應用程序上單擊表單或計時器上的按鈕離子。