从C#中的另一个类更新progressbar

时间:2019-07-20 06:28:39

标签: c# multithreading progress-bar

我在获取进度条以显示下载进度时遇到问题。这些文件正在下载,没有问题,但是由于某些原因导致进度条无法更新,所以我不知道为什么。

我尝试在downloadwc_DownloadProgressChanged方法中手动设置progressBar值,但实际上更改的唯一地方是Form1_Load方法。

using System;
using System.Windows.Forms;
using System.Threading;

namespace Launch
{
    public partial class Form1 : Form
    {

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            Downloader downloader = new Downloader();

            ThreadStart job = new ThreadStart(downloader.download);
            Thread thread = new Thread(job);
            thread.Start();

        }

        private void ProgressBar_Click(object sender, EventArgs e)
        {

        }

        public void SetProgress(int val)
        {
            progressBar.Value = val;
        }

        public void SetVisible(bool val)
        {
            progressBar.Visible = val;
        }
    }
}
using System;
using System.Data;
using System.Net;
using Newtonsoft.Json;

namespace Launch
{
    class Downloader
    {

        public void download()
        { 
            WebClient client = new WebClient();

            string url = "https://someurl.com/manifest.json";
            string json = client.DownloadString(url);

            DataSet dataSet = JsonConvert.DeserializeObject<DataSet>(json);

            DataTable dataTable = dataSet.Tables["Required"];

            foreach (DataRow row in dataTable.Rows)
            {

                string remoteUri = row["url"].ToString();
                string fileName = row["name"].ToString();

                client.DownloadProgressChanged += client_DownloadProgressChanged;
                client.DownloadFile(remoteUri, fileName);

                Console.WriteLine("Did something with " + remoteUri);

            }
        }

        private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {

            var form = new Form1();
            form.SetProgress(e.ProgressPercentage);

        }

    }
}

任何人都可以对我在这里做错的事情有所了解吗?

编辑:

我可以使用DownloadFileAsync来使大部分正常工作,但是我认为进度条是来回跳动的,因为它正在尝试计算进度每个单独的文件都以字节为单位,因此我想使用DownloadFile来完成此工作。

DownloadFile现在遇到的问题是我将其作为任务运行,但是它跳过了所有文件(不下载任何文件,只是将它们全部打印出来以超快的速度进行控制台)。

这是我当前正在使用的代码:

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

            WebClient client = new WebClient();
            client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(client_DownloadProgressChanged);

            string url = "https://someurl.com/manifest.json";
            string json = client.DownloadString(url);

            DataSet dataSet = JsonConvert.DeserializeObject<DataSet>(json);

            DataTable dataTable = dataSet.Tables["Required"];

            foreach (DataRow row in dataTable.Rows)
            {

                string remoteUri = row["url"].ToString();
                string fileName = row["name"].ToString();

                Task.Run(() => {
                    client.DownloadFile(remoteUri, fileName);
                });

                Console.WriteLine("Did something with " + remoteUri);

            }

        }

        private void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
        {

            this.BeginInvoke((MethodInvoker)delegate {
                double bytesIn = double.Parse(e.BytesReceived.ToString());
                double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
                double percentage = bytesIn / totalBytes * 100;
                label1.Text = "Downloaded ";
                label2.Text = e.BytesReceived.ToString();
                label3.Text = e.TotalBytesToReceive.ToString();
                progressBar.Value = int.Parse(Math.Truncate(percentage).ToString());
            });

        }    

有什么想法吗?

2 个答案:

答案 0 :(得分:0)

在下面使用此代码:

    private void Form1_Load(object sender, EventArgs e)
    {
        WebClient client = new WebClient();

        client.DownloadProgressChanged += client_DownloadProgressChanged;
        client.DownloadStringCompleted += client_DownloadStringCompleted;

        Uri url = new Uri("url");
        client.DownloadStringAsync(url);


    }

    void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        SetVisible(false);
    }

    void client_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
    {
        SetProgress(e.ProgressPercentage);
    }
    public void SetProgress(int val)
    {
        progressBar.Value = val;
    }

    public void SetVisible(bool val)
    {
        progressBar.Visible = val;
    }

答案 1 :(得分:0)

这可能应该属于https://codereview.stackexchange.com/

首先,不要在循环中添加处理程序

client.DownloadProgressChanged += client_DownloadProgressChanged;

第一次可以,在第二项上将被称为2倍,在第三次上将被称为3次,依此类推。您想要设置一次处理程序。将其移动到行之后:

WebClient client = new WebClient();

第二,每次触发进度更新时,您都在创建表单的新实例。一次创建一个私有变量或属性。

private Form1 form = new Form1();

编辑:

对于UI,通常只能在创建它的调度程序线程中进行修改或使用封送处理。我将其删除,因为我们已经下载了字符串async。

此外,我不会使用e.ProgressPercentage,而是类似:

Math.Truncate(e.BytesReceived / (double)e.TotalBytesToReceive * 100)