简体   繁体   English

我如何报告其他班级的背景工作者功课?

[英]How can i report a backgroundworker dowork from another class?

I want to report the progress in percentages and also to tell the user by text something like "Building maps please wait..." 我想以百分比报告进度,并通过诸如“正在制作地图,请稍候...”之类的文字告诉用户

In form1 I have all the backgroundworker1 events. 在form1中,我具有所有backgroundworker1事件。 And also set already the WorkerReportsProgress to true and the WorkerSupportsCancellation to true. 并且还已经将WorkerReportsProgress设置为true,并将WorkerSupportsCancellation设置为true。

The backgroundworker I added it to the designer from toolbox. 我将背景工作人员从工具箱中添加到设计器中。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            if (backgroundWorker1.CancellationPending == true)
            {
                e.Cancel = true;
                return; // this will fall to the finally and close everything    
            }
            else
            {
                ExtractImages ei = new ExtractImages();
                ei.Init();
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {

        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {

        }

And the class to report from: 以及要报告的课程:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Net;
using System.Xml;
using HtmlAgilityPack;

namespace SatelliteImages
{
    class ExtractImages
    {
        static WebClient client;
        static string htmltoextract;
        public static List<string> countriescodes = new List<string>();
        public static List<string> countriesnames = new List<string>();
        public static List<string> DatesAndTimes = new List<string>();
        public static List<string> imagesUrls = new List<string>();
        static string firstUrlPart = "http://www.sat24.com/image2.ashx?region=";
        static string secondUrlPart = "&time=";
        static string thirdUrlPart = "&ir=";

        public void Init()
        {
            ExtractCountires();
            foreach (string cc in countriescodes)
            {
                ExtractDateAndTime("http://www.sat24.com/image2.ashx?region=" + cc);
            }
            ImagesLinks();
        }

        public static void ExtractCountires()
        {
            try
            {
                htmltoextract = "http://sat24.com/en/?ir=true";//"http://sat24.com/en/";// + regions;
                client = new WebClient();
                client.DownloadFile(htmltoextract, @"c:\temp\sat24.html");
                client.Dispose();

                string tag1 = "<li><a href=\"/en/";
                string tag2 = "</a></li>";

                string s = System.IO.File.ReadAllText(@"c:\temp\sat24.html");
                s = s.Substring(s.IndexOf(tag1));
                s = s.Substring(0, s.LastIndexOf(tag2) + tag2.ToCharArray().Length);
                s = s.Replace("\r", "").Replace("\n", "").Replace(" ", "");

                string[] parts = s.Split(new string[] { tag1, tag2 }, StringSplitOptions.RemoveEmptyEntries);


                string tag3 = "<li><ahref=\"/en/";

                for (int i = 0; i < parts.Length; i++)
                {
                    if (i == 17)
                    {
                        //break;
                    }
                    string l = "";
                    if (parts[i].Contains(tag3))
                        l = parts[i].Replace(tag3, "");

                    string z1 = l.Substring(0, l.IndexOf('"'));
                    if (z1.Contains("</ul></li><liclass="))
                    {
                        z1 = z1.Replace("</ul></li><liclass=", "af");
                    }
                    countriescodes.Add(z1);
                    countriescodes.GroupBy(n => n).Any(c => c.Count() > 1);

                    string z2 = parts[i].Substring(parts[i].LastIndexOf('>') + 1);
                    if (z2.Contains("&amp;"))
                    {
                        z2 = z2.Replace("&amp;", " & ");
                    }
                    countriesnames.Add(z2);
                    countriesnames.GroupBy(n => n).Any(c => c.Count() > 1);
                }
            }
            catch (Exception e)
            {

            }
        }

        public void ExtractDateAndTime(string baseAddress)
        {
            try
            {
                var wc = new WebClient();
                wc.BaseAddress = baseAddress;
                HtmlDocument doc = new HtmlDocument();

                var temp = wc.DownloadData("/en");
                doc.Load(new MemoryStream(temp));

                var secTokenScript = doc.DocumentNode.Descendants()
                    .Where(e =>
                           String.Compare(e.Name, "script", true) == 0 &&
                           String.Compare(e.ParentNode.Name, "div", true) == 0 &&
                           e.InnerText.Length > 0 &&
                           e.InnerText.Trim().StartsWith("var region")
                          ).FirstOrDefault().InnerText;
                var securityToken = secTokenScript;
                securityToken = securityToken.Substring(0, securityToken.IndexOf("arrayImageTimes.push"));
                securityToken = secTokenScript.Substring(securityToken.Length).Replace("arrayImageTimes.push('", "").Replace("')", "");
                var dates = securityToken.Trim().Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries);
                var scriptDates = dates.Select(x => new ScriptDate { DateString = x });
                foreach (var date in scriptDates)
                {
                    DatesAndTimes.Add(date.DateString);
                }
            }
            catch
            {
                countriescodes = new List<string>();
                countriesnames = new List<string>();
                DatesAndTimes = new List<string>();
                imagesUrls = new List<string>();
                this.Init();
            }
        }

        public class ScriptDate
        {
            public string DateString { get; set; }
            public int Year
            {
                get
                {
                    return Convert.ToInt32(this.DateString.Substring(0, 4));
                }
            }
            public int Month
            {
                get
                {
                    return Convert.ToInt32(this.DateString.Substring(4, 2));
                }
            }
            public int Day
            {
                get
                {
                    return Convert.ToInt32(this.DateString.Substring(6, 2));
                }
            }
            public int Hours
            {
                get
                {
                    return Convert.ToInt32(this.DateString.Substring(8, 2));
                }
            }
            public int Minutes
            {
                get
                {
                    return Convert.ToInt32(this.DateString.Substring(10, 2));
                }
            }
        }

        public void ImagesLinks()
        {
            int cnt = 0;
            foreach (string countryCode in countriescodes)
            {
                cnt++;
                for (; cnt < DatesAndTimes.Count(); cnt++)
                {
                    string imageUrl = firstUrlPart + countryCode + secondUrlPart + DatesAndTimes[cnt] + thirdUrlPart + "true";
                    imagesUrls.Add(imageUrl);
                    if (cnt % 10 == 0) break;
                }
            }
        }
    }
}

In the class I want to report from the Init() the name of each country it's working. 在该类中,我想从Init()报告正在工作的每个国家/地区的名称。 So in form1 on the form on a label for example it will reportprogress on what country it's currently working when it's in the loop inside the Init() 因此,例如,在带有标签的表单上的form1中,当它位于Init()内的循环中时,它将报告当前正在哪个国家/地区工作的进度

Then to keep reporting on the same label when it's finishing with the countries to write on the label something like "Building the maps links please wait..." 然后,在国家/地区结束时,要继续在同一标签上进行报告,在标签上写上类似“正在建立地图链接,请稍候...”

And all this to report to a progressBar in the backgroundworker progresschanged event as overall working. 所有这些都报告给backgroundworker progresschanged事件中的progressBar作为整体工作。 From 0 to 100%. 从0到100%。

This is the complete form1 code. 这是完整的form1代码。 Today i'm using the webclient events to download and reportprogress the images. 今天,我正在使用webclient事件下载和报告图像进度。 So maybe somehow i should use it with the class instead the backgroundworker ? 因此,也许我应该以某种方式将其与类一起使用,而不是backgroundworker? Or use task async and await ? 还是使用任务异步并等待? Not sure. 不确定。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
using System.Net;
using System.Threading;
using System.Diagnostics;

namespace SatelliteImages
{
    public partial class Form1 : Form
    {
        WebClient webClient;               // Our WebClient that will be doing the downloading for us
        Stopwatch sw = new Stopwatch();    // The stopwatch which we will be using to calculate the download speed
        int count = 0;
        PictureBoxBigSize pbbs;

        public Form1()
        {
            InitializeComponent();

            backgroundWorker1.RunWorkerAsync();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void btnDownload_Click(object sender, EventArgs e)
        {
            //DownloadFile(ExtractImages.imagesUrls[count], @"C:\Temp\TestingSatelliteImagesDownload\" + count + ".jpg");
            // http://download.thinkbroadband.com/1GB.zip
            DownloadFile("http://download.thinkbroadband.com/1GB.zip", @"C:\Temp\TestingSatelliteImagesDownload\" + "1GB.zip");
        }

        public void DownloadFile(string urlAddress, string location)
        {
            using (webClient = new WebClient())
            {
                webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
                webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);

                // The variable that will be holding the url address (making sure it starts with http://)
                Uri URL = urlAddress.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ? new Uri(urlAddress) : new Uri("http://" + urlAddress);

                // Start the stopwatch which we will be using to calculate the download speed
                sw.Start();
                //Thread.Sleep(50);
                txtFileName.Text = count + ".jpg";
                try
                {
                    // Start downloading the file
                    webClient.DownloadFileAsync(URL, location);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        // The event that will fire whenever the progress of the WebClient is changed
        private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            // Calculate download speed and output it to labelSpeed.
            Label2.Text = string.Format("{0} kb/s", (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00"));

            // Update the progressbar percentage only when the value is not the same.
            ProgressBar1.Value = e.ProgressPercentage;

            // Show the percentage on our label.
            Label4.Text = e.ProgressPercentage.ToString() + "%";

            // Update the label with how much data have been downloaded so far and the total size of the file we are currently downloading
            Label5.Text = string.Format("{0} MB's / {1} MB's",
                (e.BytesReceived / 1024d / 1024d).ToString("0.00"),
                (e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00"));
        }

        // The event that will trigger when the WebClient is completed
        private void Completed(object sender, AsyncCompletedEventArgs e)
        {
            // Reset the stopwatch.
            sw.Reset();

            if (e.Cancelled == true)
            {
                MessageBox.Show("Download has been canceled.");
            }
            else
            {

                count++;
                DownloadFile(ExtractImages.imagesUrls[count], @"C:\Temp\TestingSatelliteImagesDownload\" + count + ".jpg");
            }
        }

        private void pictureBox1_MouseEnter(object sender, EventArgs e)
        {
            // 845, 615
            pbbs = new PictureBoxBigSize();
            pbbs.GetImages(pictureBox1);
            pbbs.Show();
        }

The main goal is first to make the class work progress and report everything to the form1 progressBar and label/s about the countries names it's currently working on and the overall progress creating the maps and links. 主要目标是首先使班级进展,并将所有内容报告给form1 progressBar并贴上有关其当前正在使用的国家/地区名称以及创建地图和链接的总体进度的标签。 Then to report each file download. 然后报告每个文件的下载。 So using the webclient now is working fine reporting the downloading of each image. 因此,现在使用webclient可以很好地报告每个图像的下载。 But the first operation in the class i'm not sure how to combine it with the form1. 但是在类中的第一个操作我不确定如何将其与form1结合。

To report progress from a background worker you have to call backgroundWorker1.ReportProgress(...); 要报告后台工作人员的进度,您必须调用backgroundWorker1.ReportProgress(...);

and provide appropriate ProgressChangedEventArgs . 并提供适当的ProgressChangedEventArgs

Your class ExtractImages actually has nothing to do with the background worker. 您的类ExtractImages实际上与后台工作程序无关。 It's purpose is to extract images and I don't think it should take the background worker as argument to make the above call itself. 目的是提取图像,我认为不应以后台工作人员作为参数来进行上述调用。 Instead I suggest to give it an event for itself to raise when it has made progress: 相反,我建议给它一个事件,以便它在取得进展时引发:

class ExtractImages
{
    // shortened

    // inherit some EventArgs
    public class ProgressEventArgs : EventArgs
    {
         public int Percentage {get;set;}
         public string StateText {get;set;}
    }

    public event EventHandler<ProgressEventArgs> ProgressChanged;

    public void Init()
    {
        ExtractCountires();
        foreach (string cc in countriescodes)
        {
            // raise event here
            ProgressChanged?.Invoke(new ProgressChangedEventArgs {Percentage = ..., StateText = cc});
            ExtractDateAndTime("http://www.sat24.com/image2.ashx?region=" + cc);
        }
        ImagesLinks();
    }
}

and subscribe that event in your DoWork method: 并在您的DoWork方法中订阅该事件:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
    if (backgroundWorker1.CancellationPending == true)
    {
        e.Cancel = true;
        return; // this will fall to the finally and close everything    
    }
    else
    {
        ExtractImages ei = new ExtractImages();
        ei.ProgressChanged += (sender, e) => backgroundWorker1.ReportProgress(e.Percentage, e);
        ei.Init();
    }
}

ProgressEventArgs can take all the status information you need. ProgressEventArgs可以获取您需要的所有状态信息。 The second argument to ReportProgress becomes the UserState property in your backgroundWorker1_ProgressChanged handler's ProgressChangedEventArgs . ReportProgress的第二个参数成为backgroundWorker1_ProgressChanged处理程序的ProgressChangedEventArgsUserState属性。


Another way is to use the IProgress<T> interface and the Progress<T> class and pass a Progress<ProgressChangedArgs> instance as argument to Init() . 另一种方法是使用IProgress<T>接口和Progress<T>类,并将Progress<ProgressChangedArgs>实例作为参数传递给Init()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何从backgroundworker dowork事件向dataGridView报告多个reportprogress值? - How can I report multiple reportprogress values from backgroundworker dowork event to a dataGridView? 如何从backgroundworker dowork事件向listView以及toolStripStatusLabel报告? - How can i report from backgroundworker dowork event to listView and also to toolStripStatusLabel? 我如何调用从backgroundworker dowork事件调用的方法? - How can i invoke a method called from backgroundworker dowork event? 如何从静态类报告进度以标记或后台工作人员? - How can i report the progress to label or a backgroundworker from static class? 如何在 backgroundworker dowork 事件中按百分比报告进度? - How to report progress by percentages in backgroundworker dowork event? 如何在后台工作者DoWork事件中启用/禁用按钮? - How can i enable/disable a button in a backgroundworker DoWork event? 我应该报告什么来报告后台工作DoWork活动的进展? - What should I report to report progress in the backgroundworker DoWork event? 如何在Backgroundworker中取消DoWork - how to cancel DoWork in Backgroundworker c#BackgroundWorker DoWork方法调用另一个类和ProgressReport - c# BackgroundWorker DoWork method calling another class and ProgressReport 我该如何为我的backgroundworker dowork事件添加经过时间的编程器? - How can i add a time elapsed progrerss to my backgroundworker dowork event?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM