我需要在backgroundworker progresschanged事件中使用invoke吗?

时间:2018-10-12 22:51:00

标签: c# winforms

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.Xml.Linq;
using System.Diagnostics;
using System.Management;
using System.Runtime.InteropServices;

namespace DownloadFiles
{
    public partial class Form1 : Form
    {
        Stopwatch sw = new Stopwatch();
        Stopwatch stopwatch = new Stopwatch();
        string filesdirectory = "Downloaded_Files";
        string mainurl = "http://www.usgodae.org/ftp/outgoing/fnmoc/models/navgem_0.5/latest_data/";
        List<string> parsedlinks = new List<string>();
        string path_exe = Path.GetDirectoryName(Application.LocalUserAppDataPath);

        List<string> results = new List<string>();
        //StreamWriter w = new StreamWriter(@"e:\monitordetector.txt");

        public Form1()
        {
            InitializeComponent();

            //DetectScreenName();

            label3.Text = "";
            label4.Text = "";
            label5.Text = "";
            label7.Text = "";
            button2.Enabled = false;
            button3.Enabled = false;
            filesdirectory = Path.Combine(path_exe, filesdirectory);
            if (!Directory.Exists(filesdirectory))
            {
                Directory.CreateDirectory(filesdirectory);
            }
            else
            {
                if (IsDirectoryEmpty(filesdirectory) == false)
                {
                    button3.Enabled = true;
                }
            }
        }

        public bool IsDirectoryEmpty(string path)
        {
            return !Directory.EnumerateFileSystemEntries(path).Any();
        }

        private string downloadhtml(string url)
        {
            backgroundWorker1.ReportProgress(0, "Downloading Main Url");
            HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
            request.Proxy = null;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader sr = new StreamReader(response.GetResponseStream());
            string html = sr.ReadToEnd();
            sr.Close();
            response.Close();
            StreamWriter w = new StreamWriter(path_exe + "\\page.html");
            w.Write(html);
            w.Close();
            return html;
        }

        int Counter = 0;
        int percentage = 0;
        int total = 0;
        int countfiletodownload = 0;
        bool processStatus = false;
        private void Parseanddownloadfiles()
        {
            downloadhtml(mainurl);
            if (bgw.CancellationPending == false)
            {
                backgroundWorker1.ReportProgress(0, "Parsing Links");
                HtmlAgilityPack.HtmlWeb hw = new HtmlAgilityPack.HtmlWeb();
                HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
                doc = hw.Load(path_exe + "\\page.html");
                foreach (HtmlAgilityPack.HtmlNode link in doc.DocumentNode.SelectNodes("//a[@href]"))
                {
                    string hrefValue = link.GetAttributeValue("href", string.Empty);
                    if (hrefValue.Contains("US"))
                    {
                        string url = "http://www.usgodae.org/ftp/outgoing/fnmoc/models/navgem_0.5/latest_data/" + hrefValue;
                        parsedlinks.Add(url);
                        if (bgw.CancellationPending == true)
                            return;
                    }
                }
                countfiletodownload = parsedlinks.Count;
                total = parsedlinks.Count;
                backgroundWorker1.ReportProgress(0, "Downloading Files");
                processStatus = true;
                for (int i = 0; i < parsedlinks.Count && bgw.CancellationPending == false; i++)
                {
                    try
                    {
                        using (WebClient client = new WebClient())
                        {
                            sw.Start();
                            Uri uri = new Uri(parsedlinks[i]);
                            string filename = parsedlinks[i].Substring(71);
                            //client.DownloadFile(parsedlinks[i], filesdirectory + "\\" + filename);
                            client.DownloadFileAsync(uri, filesdirectory + "\\" + filename);
                            Counter += 1;
                            percentage = Counter * 100 / total;
                            string filenametoreport = filename.Substring(1);
                            countfiletodownload--;
                            backgroundWorker1.ReportProgress(percentage, filenametoreport);//countfiletodownload, filenametoreport);
                        }
                    }
                    catch (Exception err)
                    {
                        string error = err.ToString();
                    }
                }
            }
        }

        /*void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {
            // Calculate download speed and output it to labelSpeed.
            if (label12.InvokeRequired)
            {
                label12.Invoke(new MethodInvoker(delegate
                {
                    label12.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.
            if (progressBar1.InvokeRequired)
            {
                progressBar1.Invoke(new MethodInvoker(delegate
                {
                    progressBar1.Value = e.ProgressPercentage;
                }));
            }

            // Show the percentage on our label.
            if (label13.InvokeRequired)
            {
                label13.Invoke(new MethodInvoker(delegate
                {
                    label13.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
            if (label14.InvokeRequired)
            {
                label14.Invoke(new MethodInvoker(delegate
                {
                    label14.Text = string.Format("{0} MB's / {1} MB's",
                        (e.BytesReceived / 1024d / 1024d).ToString("0.00"),
                        (e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00"));
                }));
            }
        }*/

        /*void client_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
        {
            // Reset the stopwatch.
            sw.Reset();

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

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        BackgroundWorker bgw;
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            bgw = (BackgroundWorker)sender;
            if (bgw.CancellationPending == true)
            {
                return;
            }
            else
            {
                Parseanddownloadfiles();
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.UserState.ToString() == "Downloading Main Url")
            {
                label3.Text = e.UserState.ToString();
            }
            if (e.UserState.ToString() == "Parsing Links")
            {
                label3.Text = e.UserState.ToString();
            }
            if (e.UserState.ToString() == "Downloading Files")
            {
                label7.Text = countfiletodownload.ToString();//parsedlinks.Count.ToString();
                label3.Text = e.UserState.ToString();
            }
            if (processStatus == true)
            {
                if (e.UserState.ToString() != "Downloading Files")
                {
                    label4.Text = e.UserState.ToString();
                    label7.Text = countfiletodownload.ToString();
                    progressBar1.Value = e.ProgressPercentage;
                    /*using (var bitmap = new Bitmap(this.Width, this.Height))
                    {
                        this.DrawToBitmap(bitmap, new Rectangle(0, 0, bitmap.Width, bitmap.Height));
                        bitmap.Save(@"e:\screens\ss.gif" + countscreenshots, System.Drawing.Imaging.ImageFormat.Gif);
                        countscreenshots += 1;
                    }*/
                }
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                string fff = null;
            }
            label3.Text = "Operation Cancelled";
            button1.Enabled = true;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            label3.Text = "Cancelling Operation";
            backgroundWorker1.CancelAsync();
            button2.Enabled = false;
            timer1.Stop();
            stopwatch.Stop();
            stopwatch.Reset();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            label3.Text = "";
            label4.Text = "";
            label7.Text = "";
            backgroundWorker1.RunWorkerAsync();
            timer1.Start();
            stopwatch.Start();
            button1.Enabled = false;
            button2.Enabled = true;
        }

        private void button3_Click(object sender, EventArgs e)
        {
            Process.Start(filesdirectory);
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            label5.Text = string.Format("{0:hh\\:mm\\:ss}", stopwatch.Elapsed);
        }
    }
}

由于某种原因,事件中的代码使整个应用程序不同步。如果我注释掉不使用的代码,那么它就可以正常工作。

我还想使用client_DownloadProgressChanged来显示和显示下载信息。

使用每次下载当前文件的progressBar信息和总体进度下载的信息来加快速度。

1 个答案:

答案 0 :(得分:2)

否*,您不需要在BackgroundWorker的ProgressChanged事件中调用。 DoWork在后台线程上运行,但是执行ProgressChanged(以及backgroundworker上的其他事件处理程序)内部代码的线程是由创建backgroundworker的线程完成的,该线程应与创建其他ui控件的线程相同因此不需要发票

*话虽如此,请密切注意我所说的BGW将使用创建BGW的线程运行ProgressChanged事件的部分。在大多数情况下,这将是UI线程。如果您使用UI线程以外的线程来创建BGW,则单击YES,则需要进行调用。如果您想简单一点,请在UI线程上与所有其他控件一起创建BGW。对于我的其余建议,我将假定您已完成此操作。

我无法完全理解您的问题,但请记住,正是UI线程运行了事件处理程序。如果您在执行一些长时任务或阻止操作时将该线程发送出去,以作为更新UI中标签的工作的一部分,那么它将使应用程序看起来已挂起。您必须让UI线程尽快完成事件处理程序中的代码。如果需要访问来自长时间操作或阻塞操作的数据,请让DoWork在提高其进度之前先计算数据,或者使用另一种方法来避免阻塞UI线程,例如异步任务模式

请注意,调用和阻止ui完全不同。 Windows控件只能由创建它们的线程访问。如果另一个线程想要访问该控件,则应使用Invoke来使ui线程执行该工作。这与通过使用UI线程从速度较慢的服务器读取50 GB的内存而不阻塞用户界面以及不使用能够使其快速回到处理窗口消息并使应用程序保持响应状态的东西这一想法完全不同