简体   繁体   English

C#Backgroundworker在标签中下载进度,在标签中获取字节

[英]C# Backgroundworker download progress in label, get bytes in label

I've created an application that patches my game servers files. 我创建了一个修补游戏服务器文件的应用程序。 However, I've got 3 problems which I can't solve: 但是,我有3个无法解决的问题:

  1. When downloading a new patch, it doesn't update the progressbar instantly, but refreshes it after around 30-40 seconds 下载新补丁时,它不会立即更新进度条,而是会在30-40秒后刷新它
  2. I want a label to show how much mega bytes they are downloading, and how much they have so far (for example: 122Mb/750Mb 我想要一个标签来显示它们正在下载多少兆字节,以及它们到目前为止有多少字节(例如:122Mb / 750Mb
  3. When downloading, I want a label to show ~% of how much it has downloaded so far 下载时,我希望标签显示到目前为止已下载量的〜%

I am not sure how to add number 2 and 3, and the number 1 problem just seems ridiculous, because there's nothing that indicates it should refresh after 30-40 seconds in my coding (at least as far as I know) 我不确定如何将数字2和3相加,而数字1的问题似乎很荒谬,因为没有任何迹象表明它应在编码30-40秒后刷新(至少据我所知)

My backgroundWorker1_DoWork: 我的backgroundWorker1_DoWork:

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        //Defines the server's update directory
        string Server = "http://localhost/dl/game-updates/";

        //Defines application root
        string Root = AppDomain.CurrentDomain.BaseDirectory;

        //Make sure version file exists
        FileStream fs = null;
        if (!File.Exists("version"))
        {
            using (fs = File.Create("version"))
            {

            }

            using (StreamWriter sw = new StreamWriter("version"))
            {
                sw.Write("1.0");
            }
        }
        //checks client version
        string lclVersion;
        using (StreamReader reader = new StreamReader("version"))
        {
            lclVersion = reader.ReadLine();
        }
        decimal localVersion = decimal.Parse(lclVersion);

        //server's list of updates
        XDocument serverXml = XDocument.Load(@Server + "Updates.xml");

        //The Update Process
        foreach (XElement update in serverXml.Descendants("update"))
        {
            string version = update.Element("version").Value;
            string file = update.Element("file").Value;

            decimal serverVersion = decimal.Parse(version);


            string sUrlToReadFileFrom = Server + file;

            string sFilePathToWriteFileTo = Root + file;

            if (serverVersion > localVersion)
            {
                Uri url = new Uri(sUrlToReadFileFrom);
                System.Net.HttpWebRequest request = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(url);
                System.Net.HttpWebResponse response = (System.Net.HttpWebResponse)request.GetResponse();
                response.Close();

                Int64 iSize = response.ContentLength;

                Int64 iRunningByteTotal = 0;

                using (System.Net.WebClient client = new System.Net.WebClient())
                {
                    using (System.IO.Stream streamRemote = client.OpenRead(new Uri(sUrlToReadFileFrom)))
                    {
                        using (Stream streamLocal = new FileStream(sFilePathToWriteFileTo, FileMode.Create, FileAccess.Write, FileShare.None))
                        {
                            int iByteSize = 0;
                            byte[] byteBuffer = new byte[iSize];
                            while ((iByteSize = streamRemote.Read(byteBuffer, 0, byteBuffer.Length)) > 0)
                            {
                                streamLocal.Write(byteBuffer, 0, iByteSize);
                                iRunningByteTotal += iByteSize;

                                double dIndex = (double)(iRunningByteTotal);
                                double dTotal = (double)byteBuffer.Length;
                                double dProgressPercentage = (dIndex / dTotal);
                                int iProgressPercentage = (int)(dProgressPercentage * 100);

                                backgroundWorker1.ReportProgress(iProgressPercentage);
                            }

                            streamLocal.Close();
                        }

                        streamRemote.Close();
                    }
                }

                //unzip
                using (ZipFile zip = ZipFile.Read(file))
                {
                    foreach (ZipEntry zipFiles in zip)
                    {
                        zipFiles.Extract(Root + "\\", true);
                    }
                }

                //download new version file
                WebClient webClient = new WebClient();
                webClient.DownloadFile(Server + "version.txt", @Root + "version");

                //Delete Zip File
                deleteFile(file);
            }
        }
    }

My backgroundWorker1_ProgressChanged: 我的backgroundWorker1_ProgressChanged:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        progressBar1.Value = e.ProgressPercentage;
        label1.Text = "Downloading updates...";
    }

And my backgroundWorker1_RunWorkerCompleted: 和我的backgroundWorker1_RunWorkerCompleted:

private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        settings_btn.Enabled = true;
        start_btn_disabled.Enabled = false;
        start_btn_disabled.Visible = false;
        start_btn.Visible = true;
        start_btn.Enabled = true;
        progressBar1.Value = 100;
        label1.Text = "Client is up to date!";
    }

Also, a side note: I'm also having a bit problems of updating labels in backgroundWorker2_DoWork? 另外,还有一个注释:我在更新backgroundWorker2_DoWork中的标签时还遇到了一些问题? Any ideas? 有任何想法吗?

Here's some working code which updates a label on Form1 using the BackgroundWorker. 这是一些使用BackgroundWorker在Form1上更新标签的工作代码。

Create a new Windows Form project and drop it in your code and it'll work. 创建一个新的Windows Form项目并将其放入您的代码中,它将起作用。 It's super ugly, but it works. 这很丑陋,但是可以用。 After that, just plug your code into the DoWork method and calculate your value and send to ReportProgress. 之后,只需将您的代码插入DoWork方法并计算您的值并发送到ReportProgress。

Keep in mind that the work done in DoWork method is the actual Background Thread. 请记住,在DoWork方法中完成的工作是实际的后台线程。 That means that in that method (DoWork) you cannot access UI (form) elements because they are on the UI thread. 这意味着在该方法(DoWork)中,您无法访问UI(表单)元素,因为它们位于UI线程上。

在此处输入图片说明

 public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            backgroundWorker1.DoWork += backgroundWorker1_DoWork;
            backgroundWorker1.ProgressChanged += backgroundWorker1_ProgressChanged;
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.RunWorkerCompleted += backgroundWorker1_RunWorkerCompleted;
        }

        void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            button1.Enabled = true;
        }

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

        void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            label1.Text = e.ProgressPercentage.ToString();
        }

        void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            FakeCountingWork();
        }


        private void FakeCountingWork()
        {
            int totalNumber = 100;
            int progressCounter = 0;
            while (progressCounter < totalNumber)
            {
                int fakecounter = 0;
                for (int x = 0; x < 100000000; x++)
                {
                    fakecounter++;
                }
                progressCounter++;
                backgroundWorker1.ReportProgress(progressCounter);
            }
        }
    }
################################## EDITED TO ADD OTHER FUNCTIONALITY ################################编辑为增加其他功能

Okay, here's how you can implement a label which displays the number of bytes downloaded so far. 好的,这是实现标签的一种方法,该标签显示到目前为止已下载的字节数。 Add a second label named label2 to your form. 在您的表单中添加另一个名为label2的标签。
Next alter the following methods from my previous example. 接下来,从我之前的示例更改以下方法。 Here we are going to use the UserState to pass an extra value to the ProgressChanged Event. 在这里,我们将使用UserState将额外的值传递给ProgressChanged事件。 It's very simple. 非常简单 You can see that I'm generating a random number and it will now appear in Label2. 您会看到我正在生成一个随机数,它现在将出现在Label2中。 This is where you could show your number of bytes. 在这里您可以显示字节数。

  void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { label1.Text = e.ProgressPercentage.ToString(); label2.Text = e.UserState.ToString(); } private void FakeCountingWork() { int totalNumber = 100; int progressCounter = 0; Random rnd = new Random(); while (progressCounter < totalNumber) { int fakecounter = 0; for (int x = 0; x < 100000000; x++) { fakecounter++; } progressCounter++; updateValue = rnd.Next(); backgroundWorker1.ReportProgress(progressCounter,updateValue); } } 

在此处输入图片说明

I would imagine this is because you are trying to update UI objects on a different thread. 我想这是因为您正在尝试在其他线程上更新UI对象。 HAve you tried using the Dispatcher if using wpf? 如果使用wpf,您是否尝试过使用Dispatcher? https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.invoke(v=vs.110).aspx https://msdn.microsoft.com/zh-CN/library/system.windows.threading.dispatcher.invoke(v=vs.110).aspx

or Invoke if using Winforms? 或如果使用Winforms则调用? https://msdn.microsoft.com/fr-ca/library/zyzhdc6b(v=vs.85).aspx https://msdn.microsoft.com/fr-ca/library/zyzhdc6b(v=vs.85).aspx

Edit: As @daylight pointed out to be, the UI was being updated in the progresschanged event, which executes on the thread which created the background worker, therefore there shouldn't be an issue regarding threading. 编辑:正如@daylight所指出的那样,UI是在progresschanged事件中更新的,该事件在创建后台工作程序的线程上执行,因此与线程无关。 See https://msdn.microsoft.com/en-us/library/ka89zff4(v=vs.110).aspx for more info 有关更多信息,请参见https://msdn.microsoft.com/zh-cn/library/ka89zff4(v=vs.110).aspx

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM