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

时间:2015-05-13 19:39:52

标签: c#

我创建了一个修补游戏服务器文件的应用程序。 但是,我遇到了3个无法解决的问题:

  1. 下载新补丁时,它不会立即更新进度条,但会在大约30-40秒后刷新它
  2. 我想要一个标签来显示他们正在下载多少字节,以及它们到目前为止有多少(例如:122Mb / 750Mb
  3. 下载时,我想要一个标签显示到目前为止下载了多少
  4. 我不知道如何添加数字2和3,而数字1问题看起来很荒谬,因为没有任何迹象表明它应该在编码30-40秒后刷新(至少据我所知)< / p>

    我的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);
                }
            }
        }
    

    我的backgroundWorker1_ProgressChanged:

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

    我的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!";
        }
    

    另外,请注意:我在backgroundWorker2_DoWork中更新标签时遇到了一些问题? 有什么想法吗?

2 个答案:

答案 0 :(得分:2)

这是一些使用BackgroundWorker在Form1上更新标签的工作代码。

创建一个新的Windows窗体项目并将其放入代码中,它将起作用。 它非常难看,但它确实有效。 之后,只需将代码插入DoWork方法并计算您的值并发送到ReportProgress。

请记住,在DoWork方法中完成的工作是实际的后台线程。 这意味着在该方法(DoWork)中,您无法访问UI(表单)元素,因为它们位于UI线程上。

enter image description here

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

好的,这是你如何实现一个标签,显示到目前为止下载的字节数。 在表单中添加名为label2的第二个标签 接下来,从我之前的示例中更改以下方法。 在这里,我们将使用UserState将额外的值传递给ProgressChanged事件。这很简单。你可以看到我正在生成一个随机数,现在它将出现在Label2中。这是您可以显示字节数的地方。

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

enter image description here

答案 1 :(得分:0)

我想这是因为你试图在不同的线程上更新UI对象。如果使用wpf,您是否尝试过使用Dispatcher? https://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.invoke(v=vs.110).aspx

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

编辑: 正如@daylight指出的那样,UI正在progresschanged事件中更新,该事件在创建后台工作程序的线程上执行,因此不应该是有关线程的问题。有关详细信息,请参阅https://msdn.microsoft.com/en-us/library/ka89zff4(v=vs.110).aspx