2012-10-19 12 views
0

일시 중지 및 다시 시작하지 않고 취소/중지한다는 의미입니다. 일시 중지 내가 Form1의 상단이 사용하고 다시 시작하려면 :) (_busy.Reset을하고 메신저 버튼에서 다음어떻게 재귀 루프를 멈출 수 있습니까?

System.Threading.ManualResetEvent _busy = new System.Threading.ManualResetEvent(true); 

; 및 _busy.Set(); 일시 중지하고 다시 시작합니다. 하지만 필사적으로 반복적 인 루프를 중지/취소하고 싶습니까?

이 재귀 루프 코드입니다 : 내가위한 버튼의 클릭 이벤트가

private List<string> test(string url, int levels,DoWorkEventArgs eve) 
     { 
      _busy.WaitOne(); 
      if (cancel == true) 
      { 

      } 
      this.Invoke(new MethodInvoker(delegate { label3.Text = label3.Text = (Int32.Parse(label12.Text) + Int32.Parse(label10.Text)).ToString(); })); 


      HtmlWeb hw = new HtmlWeb(); 
      List<string> webSites; 
      List<string> csFiles = new List<string>(); 

      csFiles.Add("temp string to know that something is happening in level = " + levels.ToString()); 
      csFiles.Add("current site name in this level is : " + url); 
      try 
      { 
       this.Invoke(new MethodInvoker(delegate { ColorText.Texts(richTextBox1, "Level: " + levels.ToString(), Color.Green); })); 
       this.Invoke(new MethodInvoker(delegate { ColorText.Texts(richTextBox1, " Loading The Url: " , Color.Red); })); 
       this.Invoke(new MethodInvoker(delegate { ColorText.Texts(richTextBox1, url + "...",Color.Blue); })); 
       HtmlAgilityPack.HtmlDocument doc = TimeOut.getHtmlDocumentWebClient(url, false, "", 0, "", ""); 

       this.Invoke(new MethodInvoker(delegate { ColorText.Texts(richTextBox1, " Done " + Environment.NewLine, Color.Red); })); 


        currentCrawlingSite.Add(url); 
        webSites = getLinks(doc); 
        removeDupes(webSites); 
        removeDuplicates(webSites, currentCrawlingSite); 
        removeDuplicates(webSites, sitesToCrawl); 
        if (removeExt == true) 
        { 
         for (int i = 0; i < webSites.Count; i++) 
         { 
          webSites.Remove(removeExternals(webSites)); 
         } 
        } 
        if (downLoadImages == true) 
        { 
         webContent.retrieveImages(url);      } 
        } 
        if (levels > 0) 
         sitesToCrawl.AddRange(webSites) 
        this.Invoke(new MethodInvoker(delegate { label7.Text = sitesToCrawl.Count.ToString(); })); 
        this.Invoke(new MethodInvoker(delegate { label12.Text = currentCrawlingSite.Count.ToString(); })); 


        if (levels == 0) 
        { 
         return csFiles; 
        } 
        else 
        { 


         for (int i = 0; i < webSites.Count(); i++)//&& i < 20; i++)       { 



          string t = webSites[i]; 
          if ((t.StartsWith("http://") == true) || (t.StartsWith("https://") == true)) 
          { 
           csFiles.AddRange(test(t, levels - 1, eve));         
          } 

         } 
         return csFiles; 
        } 



      } 
      catch 
      { 
       failedUrls++; 
       this.Invoke(new MethodInvoker(delegate { label10.Text = failedUrls.ToString(); })); 
       this.Invoke(new MethodInvoker(delegate { ColorText.Texts(richTextBox1, " Failed " + Environment.NewLine, Color.Green); })); 
       return csFiles; 
      } 

     } 

의 I는 내가 한 이상 내가 재귀 루프에서 다음 true로 설정 플래그가이 중지/취소 :

if (cancel == true) 
      { 

      } 

break;을 추가하려고했으나 그 동안 또는하지 않은 동안 사용하지 마십시오.

어떻게하면됩니까?

감사합니다.

+3

예를 들어 이라는 적절한 return 문을 사용하십시오. return new List (); – derape

+0

결말이없는 재귀 함수를 작성했다면 위험한 영역입니다. 재귀 기능은 exit '전략'이 코딩 된 경우에만 작동합니다. 코드를 멈추고 전임자에게 돌아갈 필요가있는'return;'문을 사용하십시오. (또한'return;'등을 호출합니다 ...) – Flater

+1

... 그렇지 않으면 결국 끝날 것입니다 스택 오버 플로우 ... –

답변

1

나는 완전한 대답을 게시 할 것이다 :-)
재귀 함수의 문제는 재귀 적이다. 언제 그만 둘 것인지 모르는 한 영원히 계속됩니다.
그래서 필요한 것은 그것을 끝내기위한 조건입니다. 메서드는 자체적으로 반복 호출하기 때문에 기본적으로 호출 스택을 다시 올리고 뭔가를 반환해야하는 다른 메서드에서 일반적으로 수행하는 것처럼 반환해야합니다. 당신은 분명히 당신이 당신의 목록 ;-)

에 필요한 모든 것을 넣어 것

if (cancel) 
{ 
    return new List<string>(); 
} 

:
작은 예는 그래서 당신은 적절한 return 문을 필요로 재귀 루프를 종료하고 당신이 필요로 복귀하기 위해 here 을 게시

관련 문제