【问题标题】:How To Optimize BackgroundWorker, Implemented Process Is Slow.如何优化BackgroundWorker,实现过程慢。
【发布时间】:2015-02-19 18:14:25
【问题描述】:

我为 BackgroundWorker 和进度条实现了“CheckFileSize()”函数,因为搜索任务可能需要很长时间。由于添加了 BackgroundWorker 线程,应用程序时间似乎要慢得多..我该如何优化,或者我做错了什么?

        private void UploadApp()
        {
            label4.Visible = true;
            label4.Text = ("Please wait...");

            // Assign BackgroundWorker1 to start check file size.
            backgroundWorker1.RunWorkerAsync();
        }


        // Check for invalid file size in 'AppID' folder.       
        private void CheckFileSize()
        {
            // Set application directory.
            string AppDirectory = ("Z:/Projects/" + AppID);

            // Set maximum file size in byte size (2GB).
            long fileSizeLimit = 2000000000;

            // Get IEnumerable (as in a list) on all files by recursively scanning directory.
            var fileList = Directory.EnumerateFiles(AppDirectory, "*", SearchOption.AllDirectories);

            // Retrieve the size of files.
            long fileSize    = (from file in fileList let fileInfo = new FileInfo(file) select fileInfo.Length).Sum();

            // Exit application utility if maximum file size found.
            if (fileSize >= fileSizeLimit)
            {
                //MessageBox.Show("Project folder '" + AppID + "' contain file size greater than or equal 2GB.  Manual SCM upload required.");
                DialogResult MsgResult;
                MsgResult = MessageBox.Show("Project folder '" + AppID + "' contain file size greater than or equal 2GB.  Manual SCM upload required.",
                                            "Invalid File Size",
                                            MessageBoxButtons.OK,
                                            MessageBoxIcon.Error);                
                Environment.Exit(0);
            } 
          }


        // BackgroundWorker1 runs 'DoWork' in the background to check invalid file size.
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            // Set for loop to increment progress bar.
            for (int i = 0; i <= 100; i++)
            {
                CheckFileSize();

                // Method to report the percentage complete.
                backgroundWorker1.ReportProgress(i);

                // Cancel BackgroundWorker1.
                if (backgroundWorker1.CancellationPending)
                {
                    break;
                }                
            }
        }


        // Update the progress bar control when the worker thread reports progress.
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
        }


        // Enable START and EXIT button when work is done or thread is cancelled.
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            button1.Enabled = true;
            button2.Enabled = false;
            button3.Enabled = true;
        }                                 
    }

【问题讨论】:

    标签: c# performance optimization process backgroundworker


    【解决方案1】:

    您在循环中调用 CheckFileSize,这非常昂贵。您最好使用 FileSystemWatcher 来通知您对文件的任何更改。然后,您可以跟踪每个文件大小的变化并相应地更新总数。

    【讨论】:

      【解决方案2】:

      我认为这不是从BackgroundWorker 报告进度的方式。你正在做的是:

      1. 运行 CheckFileSize 方法 100 次
      2. 每次跑步后,进度提高 1%。

      据我所知,CheckFileSize 的所有 100 次运行都做同样的事情。结果可以改变的唯一方法是目录的内容在运行之间发生变化。所以,问题是 - 您是否希望在代码运行时文件会发生变化?

      如果没有,那么您应该只运行一次CheckFileSize。如果你需要报告进度百分比,你必须在方法内部这样做:

      var fileList = Directory.GetFiles(AppDirectory, "*", SearchOption.AllDirectories);
      int fileCounter = 0;
      
      long fileSize = 0;
      
      foreach (string file in fileList)
      {
          fileSize += new FileInfo(file).Length;
          if (fileSize >= fileSizeLimit)
          {
              //display message box etc.
              break;
          }
          fileCounter++;
          backgroundWorker1.ReportProgress(((double)fileCounter/fileList.Count)*100);
      }
      

      这还有另一个优化 - 当达到限制时循环结束,因此我们不必查看其余文件的大小(您的代码总是会遍历所有文件)。

      如果目录内容可以更改,那么我真的不知道如何显示进度条,我可能会按照 Tarik 的建议使用 FileSystemWatcher

      除此之外,我不太喜欢Environment.Exit 的用法。我相信最好停止BackgroundWorker,设置一个结果并在RunWorkerCompleted处理程序中处理它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-07
        • 2012-11-12
        • 2014-06-30
        相关资源
        最近更新 更多