如何优化BackgroundWorker,实现的进程很慢。

时间:2015-02-19 18:14:26

标签: c# performance optimization process backgroundworker

我为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;
        }                                 
    }

2 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

我认为这不是BackgroundWorker报告进展的方式。你在做什么:

  1. 运行CheckFileSize方法100次
  2. 每次运行后,将进度提高1%。
  3. 据我所知,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处理程序中处理它。