1

我有一个进度条,显示后台工作人员 do_dowork 事件返回的进度,如下所示。

       if (ftpSourceFilePath.Scheme == Uri.UriSchemeFtp)
            {
                FtpWebRequest objRequest = (FtpWebRequest)FtpWebRequest.Create(ftpSourceFilePath);
                NetworkCredential objCredential = new NetworkCredential(userName, password);
                objRequest.Credentials = objCredential;
                objRequest.Method = WebRequestMethods.Ftp.DownloadFile;
                FtpWebResponse objResponse = (FtpWebResponse)objRequest.GetResponse();
                StreamReader objReader = new StreamReader(objResponse.GetResponseStream());
                int len = 0;
                int iProgressPercentage = 0;
                FileStream objFS = new FileStream((cd+"\\VolareUpdate.rar"), FileMode.Create, FileAccess.Write, FileShare.Read);

                    while ((len = objReader.BaseStream.Read(buffer, 0, buffer.Length)) > 0)
                        {

                            objFS.Write(buffer, 0, len);
                            iRunningByteTotal += len;
                            double dIndex = (double)(iRunningByteTotal);
                            double dTotal = (double)buffer.Length;
                            double dProgressPercentage =  (dIndex / dTotal);

                            iProgressPercentage = (int)(dProgressPercentage);

                            if (iProgressPercentage > 100)
                            {
                                iProgressPercentage = 100;

                            }

                            bw.ReportProgress(iProgressPercentage);


                        }
}

但是,我的进度条没有更新。在搜索时,我被告知 UI 线程被阻塞,然后我认为可能将进度传递到循环之外就可以了。然后我改成这个

if (ftpSourceFilePath.Scheme == Uri.UriSchemeFtp)
                {
                    FtpWebRequest objRequest = (FtpWebRequest)FtpWebRequest.Create(ftpSourceFilePath);
                    NetworkCredential objCredential = new NetworkCredential(userName, password);
                    objRequest.Credentials = objCredential;
                    objRequest.Method = WebRequestMethods.Ftp.DownloadFile;
                    FtpWebResponse objResponse = (FtpWebResponse)objRequest.GetResponse();
                    StreamReader objReader = new StreamReader(objResponse.GetResponseStream());
                    int len = 0;
                    int iProgressPercentage = 0;
                    FileStream objFS = new FileStream((cd+"\\VolareUpdate.rar"), FileMode.Create, FileAccess.Write, FileShare.Read);
    while ((len = objReader.BaseStream.Read(buffer, 0, buffer.Length)) > 0)
                        {

                            objFS.Write(buffer, 0, len);
                            iRunningByteTotal += len;
                            double dIndex = (double)(iRunningByteTotal);
                            double dTotal = (double)buffer.Length;
                            double dProgressPercentage =  (dIndex / dTotal);

                            iProgressPercentage = (int)(dProgressPercentage);

                            if (iProgressPercentage > 100)
                            {
                                iProgressPercentage = 100;

                            }
                           // System.Threading.Thread.Sleep(2000);
                              iProgressPercentage++;
                         //    SetText("F", true);




                        }

                         bw.ReportProgress(iProgressPercentage);
                         progressBar.Refresh();

}

然而仍然没有帮助。当我在 workerprogresschanged 事件中设置断点时,它会显示 progressbar.value 但不会更新。我尝试了progressbar.update(0,我也尝试在循环中将线程休眠一段时间仍然没有帮助。请任何建议/帮助将不胜感激。

4

4 回答 4

0

没错,你不能从 dowork() 方法访问 UI Thread。您需要使用 progresschanged 事件。

看看http://www.codeproject.com/Tips/83317/BackgroundWorker-and-ProgressBar-demoC#,使用不同类的后台 Worker 更新进度条

于 2013-11-06T04:43:56.803 回答
0
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }
于 2013-11-06T04:48:27.843 回答
0

我认为您错过了对 Application.DoEvents() 的调用

在像循环这样的长时间运行的任务中,如果您想进行任何 UI 更改,那么您应该调用

Application.DoEvents()

这将反映对 UI 所做的更改。

于 2013-11-06T05:34:35.853 回答
0

感谢您的所有回复。我使用如下委托方法实现了这一点。

  delegate void SetProgressBar(int percentage, bool logic);
        private void SetProgress(int percentage, bool logic)
        {
            if (progressBar.InvokeRequired)  
            {
                SetProgressBar d = new SetProgressBar(SetProgress);
                this.Invoke(d, new object[] { percentage, logic });

            }
            else
            {

                progressBar.Style = ProgressBarStyle.Blocks;
                progressBar.Value = percentage;
                progressBar.Text = percentage.ToString() + "%";

            }


        }

还有我的工作活动

private void bw_DoWork(object sender, DoWorkEventArgs e)
 {
            BackgroundWorker worker = sender as BackgroundWorker;


  while ((len = objReader.BaseStream.Read(buffer, 0, buffer.Length)) != 0)
                        {
                           .....

                          .......
                            int iProgressPercentage = (int)(dProgressPercentage * 100);
                            bw.ReportProgress(iProgressPercentage);

                        }
}

在我的 Progress changed 事件中,触发上面的委托方法。

   private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {


             SetProgress(e.ProgressPercentage, true);


        }

这很有效,没有问题...感谢您的所有贡献。

于 2013-11-12T06:53:46.343 回答