簡體   English   中英

我如何報告其他班級的背景工作者功課?

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

我想以百分比報告進度,並通過諸如“正在制作地圖,請稍候...”之類的文字告訴用戶

在form1中,我具有所有backgroundworker1事件。 並且還已經將WorkerReportsProgress設置為true,並將WorkerSupportsCancellation設置為true。

我將背景工作人員從工具箱中添加到設計器中。

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)
        {

        }

以及要報告的課程:

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;
                }
            }
        }
    }
}

在該類中,我想從Init()報告正在工作的每個國家/地區的名稱。 因此,例如,在帶有標簽的表單上的form1中,當它位於Init()內的循環中時,它將報告當前正在哪個國家/地區工作的進度

然后,在國家/地區結束時,要繼續在同一標簽上進行報告,在標簽上寫上類似“正在建立地圖鏈接,請稍候...”

所有這些都報告給backgroundworker progresschanged事件中的progressBar作為整體工作。 從0到100%。

這是完整的form1代碼。 今天,我正在使用webclient事件下載和報告圖像進度。 因此,也許我應該以某種方式將其與類一起使用,而不是backgroundworker? 還是使用任務異步並等待? 不確定。

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();
        }

主要目標是首先使班級進展,並將所有內容報告給form1 progressBar並貼上有關其當前正在使用的國家/地區名稱以及創建地圖和鏈接的總體進度的標簽。 然后報告每個文件的下載。 因此,現在使用webclient可以很好地報告每個圖像的下載。 但是在類中的第一個操作我不確定如何將其與form1結合。

要報告后台工作人員的進度,您必須調用backgroundWorker1.ReportProgress(...);

並提供適當的ProgressChangedEventArgs

您的類ExtractImages實際上與后台工作程序無關。 目的是提取圖像,我認為不應以后台工作人員作為參數來進行上述調用。 相反,我建議給它一個事件,以便它在取得進展時引發:

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();
    }
}

並在您的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可以獲取您需要的所有狀態信息。 ReportProgress的第二個參數成為backgroundWorker1_ProgressChanged處理程序的ProgressChangedEventArgsUserState屬性。


另一種方法是使用IProgress<T>接口和Progress<T>類,並將Progress<ProgressChangedArgs>實例作為參數傳遞給Init()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM