2009-10-26 2 views
0

작은 코드 샘플이 있습니다.Stack.Overflow 오류 - WinForms App Vs. WinService

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

메서드 GetAllItems가 DB로 이동하여 컬렉션에 대한 모든 새 항목을 가져옵니다 -> 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로 이동하여 일부 업데이트를 한 다음 GetItems 메서드를 호출하여 allItems 컬렉션을 다시 채울 필요가 있습니다.

이 유형의 코드는 WinFormsApp에서 Stack.Overflow 예외를 발생시킵니다. 두 가지 질문이 있습니다.
1. 동일한 코드를 사용하여 WinService 응용 프로그램에서이 예외 유형이 throw됩니까?
2. 자기 호출 메소드 대신 타이머를 사용하는 것에 대한 귀하의 의견은 무엇입니까?

답변

1

"자체 호출 메서드"는 더 정확하게 "recursive method"이라고합니다. 당신의 해결책은 창조적입니다. 나는 그것을 줄 것입니다. 그러나 그것을하지 마십시오. 스택 공간은 매우 제한되어 있습니다. 서비스로 이동할 때이 문제가 나타나며이를 처리하는 훨씬 더 좋은 방법이 있습니다. 타이머는 서비스에서 사용될 때 매우 적합합니다.

+0

첫 번째 구현은 타이머를 사용하도록 계획되었습니다. 하지만 한 가지 문제가있었습니다. 타이머가 1 초에 눈금으로 설정됩니다. CheckAllItems() 작업이 완료되지 않고 타이머가 다시 틱하면 어떻게됩니까? 코드에 대한 설명이 거의 없습니다. 재귀 호출이 있어야 모니터링이 중지되지 않습니다. – ZokiManas

+1

@ZM : System.Timers.Timer 클래스를 사용하고 이전 이벤트 처리가 완료되기 전에 타이머가 다시 틱하면 처리기가 다른 스레드에서 다시 호출됩니다. 코드가이를 처리 할 수 ​​있는지 확인하십시오. 즉, 코드가 재진입 가능한지 확인하십시오. 이 동작을 원하지 않으면 처리기에서 타이머를 중지() 한 다음 완료되면 다시 시작() 할 수 있습니다. –

+0

@ZM : 이전에 명확하지 않은 경우 재귀 호출이 나쁜 생각 일뿐만 아니라 ** 정말 나쁜 생각입니다. 하지 마. –

1

귀하의 경우 재귀 호출 방법은 타이머를 사용하는처럼 입니다. 당신도 그 일을해서는 안됩니다 !!

간단한 루프를 사용하고 잠시 동안 잠자기 상태로 스레드를 보냅니다.

+0

@Foxfire : 타이머에 무슨 문제가 있습니까? –

+0

+1 타이머가 좋지 않습니다. –

+0

올바르게 사용하면 아무것도 표시되지 않습니다. 그러나 그가 이와 같은 코드를 작성하면, 재귀를 유발할 수도있는 잘못된 장소에 타이머를 생성 할 것을 두려워합니다. 실제로 재귀를 찾는 것이 훨씬 어렵습니다. – Foxfire

0

MS IL에는 .tail op 코드가 있습니다. 하지만 C#은 꼬리 재귀를 인식하고 싶다. (그런데 tail re recursion은 매우 느리다. (

0

왜 재귀를해야 하는가? 메소드가 멈출 수있는 흐름 제어문이 없다. ...

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

이을 : 재귀과 체인을 종료 무한 재귀가 오버 플로우를 일으키는 것을 아마 더 나은 솔루션이 것 모두 떨어져 재귀 수행 할 다른 래퍼를 제거하면 재귀하지 않고 동일한 결과를 달성한다 루프에서 멈추지 않고 동일한 결과를 얻을 수 있습니다. 그런 다음 실행 환경의 컨텍스트에서 호출을 반복하는 규칙을 구현할 수 있습니다. 단추는 서비스 응용 프로그램의 폼이나 타이머를 클릭합니다. 이온.