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

C#Backgroundworker在标签中下载进度,在标签中获取字节,c#,C#,我已经创建了一个应用程序来修补我的游戏服务器文件。 然而,我有三个问题无法解决: 下载新补丁时,它不会立即更新progressbar,但会在大约30-40秒后刷新它 我想要一个标签来显示他们下载了多少兆字节,以及到目前为止有多少兆字节(例如:122Mb/750Mb) 下载时,我想要一个标签来显示~%的下载量 我不知道如何添加数字2和3,而数字1的问题似乎很可笑,因为在我的编码中,没有任何东西表明它应该在30-40秒后刷新(至少据我所知) 我的背景工作: private void backgrou

我已经创建了一个应用程序来修补我的游戏服务器文件。 然而,我有三个问题无法解决:

  • 下载新补丁时,它不会立即更新progressbar,但会在大约30-40秒后刷新它
  • 我想要一个标签来显示他们下载了多少兆字节,以及到目前为止有多少兆字节(例如:122Mb/750Mb)
  • 下载时,我想要一个标签来显示~%的下载量
  • 我不知道如何添加数字2和3,而数字1的问题似乎很可笑,因为在我的编码中,没有任何东西表明它应该在30-40秒后刷新(至少据我所知)

    我的背景工作:

    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);
                }
            }
        }
    
    我的背景工作1\u进度发生了变化:

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            label1.Text = "Downloading updates...";
        }
    
    我的后台工作人员1_runworker已完成:

    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\u DoWork中更新标签时也遇到了一些问题?
    有什么想法吗?

    我想这是因为您试图在不同的线程上更新UI对象。如果使用wpf,您是否尝试过使用Dispatcher

    如果使用Winforms,是否调用

    编辑:
    正如@daylight指出的那样,UI在progresschanged事件中被更新,该事件在创建后台工作线程的线程上执行,因此线程方面不应该存在问题。有关更多信息,请参阅这里的一些工作代码,使用BackgroundWorker更新Form1上的标签

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

    请记住,DoWork方法中完成的工作是实际的后台线程。 这意味着在该方法(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);
                }
            }
        }
    

    公共部分类表单1:表单
    {
    公共表格1()
    {
    初始化组件();
    backgroundWorker1.DoWork+=backgroundWorker1_DoWork;
    backgroundWorker1.ProgressChanged+=backgroundWorker1\u ProgressChanged;
    backgroundWorker1.WorkerReportsProgress=true;
    backgroundWorker1.RunWorkerCompleted+=backgroundWorker1\u RunWorkerCompleted;
    }
    void backgroundWorker1\u RunWorkerCompleted(对象发送方,runworkercompletedeventarge)
    {
    按钮1.启用=真;
    }
    私有无效按钮1\u单击(对象发送者,事件参数e)
    {
    按钮1.启用=错误;
    backgroundWorker1.RunWorkerAsync();
    }
    void backgroundWorker1\u ProgressChanged(对象发送方,ProgressChangedEventArgs e)
    {
    label1.Text=e.ProgressPercentage.ToString();
    }
    无效backgroundWorker1\u DoWork(对象发送方,DoWorkerVentargs e)
    {
    伪造计数工作();
    }
    私人无效伪造计数工作()
    {
    整数总数=100;
    int progressCounter=0;
    while(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);
                }
            }
    
    void backgroundWorker1\u ProgressChanged(对象发送方,ProgressChangedEventArgs e)
    {
    label1.Text=e.ProgressPercentage.ToString();
    label2.Text=e.UserState.ToString();
    }
    私人无效伪造计数工作()
    {
    整数总数=100;
    int progressCounter=0;
    随机rnd=新随机();
    while(progressCounter

    此网站上的欢迎可能重复。John。如果你想有更好的机会得到回答,请看以下内容:@demonplus该帖子上的人正在使用backgroundworker插入mysql值。我不是。你应该先阅读该帖子,然后再说这是一个duplicate@JohnK当有人建议复制时,可能意味着其中有代码对你有用的问题-我认为你错了。你的问题部分是关于在使用
    BackgroundWorker
    时更新标签的,这与链接的问题相同。哦,我的错。对不起,@demonplus。我认为@demonplus发布的链接会有帮助。不管后台工作人员在做什么,它都是有用的是一个与UI对象所在线程不同的线程,所以你不能像平常一样更新它们。实际上,他似乎正在更新UI线程对象(标签)仅在ProgressChanged事件中这样做是正确的。使用ProgressChanged事件更新UI元素是正确的方法,您可以在我更新表单标签的答案中看到这一点。您无法从DoWork()访问UI(表单)元素方法---这是一个单独的执行线程,将失败。@daylight