【问题标题】:How do i use a backgroundworker and report to the progressBar the right way?我如何使用后台工作人员并以正确的方式向进度条报告?
【发布时间】:2012-09-12 04:32:12
【问题描述】:

在这种情况下,progressBar 的移动速度比真正的 Dowork 进度更快,然后在 progressChanged 事件中抛出异常,即 progressBar 值超过 100%,那么这里有什么问题我该如何计算并以正确的方式报告它?

private List<string> webCrawler(string url, int levels , DoWorkEventArgs eve)
        {
            bool already = false;
                HtmlAgilityPack.HtmlDocument doc;
                HtmlWeb hw = new HtmlWeb();
                List<string> webSites;// = new List<string>();
                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
                {
                    doc = hw.Load(url);
                    webSites = getLinks(doc);


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

                        int actual_sites = 0;
                        for (int i = 0; i < webSites.Count() && i < 20; i++)                         {
                            if ((worker.CancellationPending == true))
                            {
                                eve.Cancel = true;
                                break;
                            }
                            else
                            {

                                string t = webSites[i];
                                                                if ((t.StartsWith("http://") == true) || (t.StartsWith("https://") == true)) // replace this with future FilterJunkLinks function
                                {
                                    for (int e = 0; e < csFiles.Count; e++)
                                    {
                                        if (csFiles[e].Contains(t))
                                        {
                                            already = true;

                                        }
                                    }

                                    if (!already)
                                    {
                                        actual_sites++;
                                        csFiles.AddRange(webCrawler(t, levels - 1,eve));
                                        this.Invoke(new MethodInvoker(delegate { Texts(richTextBox1, "Level Number " + levels + " " + t + Environment.NewLine, Color.Red); }));
                                        worker.ReportProgress(i * 10);
                                                                            }

                                }
                            }
                        }

                        return csFiles;
                    }



                }
                catch
                {
                    return csFiles;
                }

        }




        public void Texts(RichTextBox box, string text, Color color)
        {
            box.SelectionStart = box.TextLength;
            box.SelectionLength = 0;

            box.SelectionColor = color;
            box.AppendText(text);
            box.SelectionColor = box.ForeColor;
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            worker = sender as BackgroundWorker;
            webCrawler(guys, 2,e);
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            this.progressBar1.Value = e.ProgressPercentage;

        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

        }

        private void button1_Click(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
        } 

我在 DoWork 事件中传递了 DoWorkEventsArgs 的变量 e,因此如果我需要取消操作,我可以在 webCrawler 函数中使用工作变量。在 webCrawler 中,我称它为 DoWorkEventArgs 前夕。

问题是向progressBar报告的方式不对。

尝试报告进度为:

for (int i = 0; i < webSites.Count() && i < 20; i++)                         {
                            double incPercent = (1 / webSites.Count()); 
                            if ((worker.CancellationPending == true))
                            {
                                eve.Cancel = true;
                                break;
                            }
                            else
                            {

                                string t = webSites[i];
                                                                if ((t.StartsWith("http://") == true) || (t.StartsWith("https://") == true)) // replace this with future FilterJunkLinks function
                                {
                                    for (int e = 0; e < csFiles.Count; e++)
                                    {
                                        if (csFiles[e].Contains(t))
                                        {
                                            already = true;

                                        }
                                    }

                                    if (!already)
                                    {
                                        actual_sites++;
                                        csFiles.AddRange(webCrawler(t, levels - 1,eve));
                                        this.Invoke(new MethodInvoker(delegate { Texts(richTextBox1, "Level Number " + levels + " " + t + Environment.NewLine, Color.Red); }));
                                        worker.ReportProgress(i * (int)incPercent);

【问题讨论】:

  • 您将进度百分比设置为i * 10。当您拥有超过 10 个网站时会发生什么?
  • 另外,您可以将文本框字符串作为ProgressChangedEventArgs.UserState 传递,而不是做所有Invoke 的事情。
  • Blordgbeard 是真的。所以我必须只使用变量 i 吗?还是只有变量 actual_sites ?我尝试只使用 i 然后只使用 actual_sites 但每次进度条有点进展时它都不能正常工作然后重新开始。

标签: c#


【解决方案1】:
worker.ReportProgress(i * 10);

只要 i > 10(即超过 10 页),您的进度条就会超过 100%。

如果你真的想按百分比来做,我会这样做:

double incPercent = (1 / webSites.Count())

.
.
.
.
worker.ReportProgress(i * incPercent );

作为旁注,您的变量名称和间距似乎.. 有点偏离

编辑:抱歉,当执行两个数字的除法并且您希望结果为双精度时,您必须确保除数或被除数的类型为双精度。否则,您正在有效地执行 int / int,这会给您一个 int 返回。您可能知道, int 会截断您的小数点。这就是您在计算中为零的原因。

此外,reportProgress 方法的取值范围为 0 到 100,因此您必须将最终结果乘以 100。

像这样修复你的代码:

double incPercent = (1 / (double)webSites.Count())

.
.
.
.
worker.ReportProgress(i * incPercent * 100 );

【讨论】:

  • i46kok 变量 incPercent 在网站第一次包含 25 时始终为 0.0,但在使用断点时结果仍显示为 0.0。
  • 即使我只是在做 double incPercent 1 / 25;结果是 0.0 奇怪。如果我做 1 / 1 结果是 1.0 但 1 / 25 给出 0.0
  • 执行时:double incPercent = ((double)1 / webSites.Count());那么结果是 0.04,但 progressChanged 事件中的报告如果一直是 0。
猜你喜欢
  • 2010-10-25
  • 1970-01-01
  • 2022-06-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多