0

我的意思不是暂停和恢复,而是取消/停止。要暂停和恢复,我在 Form1 的顶部使用它:

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

然后在按钮中我正在做 _busy.Reset(); 和 _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;
            }

        }

我有一个用于取消/停止的按钮单击事件,我有一个设置为 true 的标志,然后在上面的递归循环中我做了:

if (cancel == true)
            {

            }

试图添加break;但它不是 for or while 所以你不能使用 break;

我该怎么做?

谢谢。

4

1 回答 1

1

好的,我将发布一个完整的答案 :-)
递归函数的问题是,它们是递归的。只要你不知道什么时候退出它,它就会永远运行。
所以你需要一个条件来完成它。由于该方法一遍又一遍地调用它自己,因此您基本上需要再次向上调用堆栈并返回一些东西,就像您通常在任何其他应该返回一些东西的方法中所做的那样。此处
发布了一个小示例 因此,为了退出递归循环,您需要一个正确的 return 语句并返回您需要的内容:

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

你显然会把你需要的一切都放在你的清单中;-)

于 2012-10-19T07:30:34.293 回答