使用后台工作程序 – 更新ProgressBar以了解递归方法的进度

下面是一个方法,我想发送到后台工作者,但我正在努力如何根据如何创建我的方法来做到这一点。 尽管如此,它不会返回任何正常的内容,但每次调用时都需要一个directoryInfo对象。

private void getSizeForTargetDirectory(DirectoryInfo dtar) { // generate a collection of objects. files comes first and then directories. foreach (Object item in collection ) { if (item == file) { track the size of the files as you encounter. } else if (item == directory) { // found a new directory, recall the method. !!! } } } 

这是我第一次使用后台工作人员,所以我有点陷入困境,我尝试通过这里找到的帮助实现了一些东西但是当我意识到我的方法是递归的时候卡住了。

如何在繁忙循环期间显示进度?

我实现了一个doWork事件处理程序方法,但注意到如果我有更多的文件和文件夹要在较低的子级别上处理,我需要以某种方式回忆该方法。

我有一个简单的按钮单击事件处理程序,当当前所选节点是目录时,它调用我的’getSizeForTargetDirectory()’方法。

  private void retrieveInfoButton_Click(object sender, EventArgs e) { // check to see if the path is valid // reset the labels and textfields. string fullPath = treeDrives.SelectedNode.FullPath; string sNodesName = treeDrives.SelectedNode.Text; if (directory) // Enter here if its a directory. { string parentPath = treeDrives.SelectedNode.Parent.FullPath; DirectoryInfo[] dirArray = populateFoldersArray(parentPath); for (int i = 0; i < dirArray.Length; i++) { if (dirArray[i].Name == sNodesName) { getSizeForTargetDirectory(dirArray[i]); // do work ! 

希望这能解释我想要做什么以及我是如何做到的。 问题是当我尝试发布的大部分工作来自递归方法时,我如何使用后台工作者类的报告进度function。

通过早期测试,我注意到我的getSize方法经过一些调整后非常高效,并且报告当前提供的文件夹的大小信息非常快,但是我再次使用相当强大的开发机器,因此对于所有用户来说可能并非如此。

感谢阅读,希望有人可以帮助!

我认为使用DirectoryDirectoryInfo上的内置方法使用递归搜索选项获取所有目录或文件要简单得多:

 public partial class Form1 : Form { private Action updateProgMethod; public Form1() { InitializeComponent(); } private void Form1_Load(object sender, EventArgs e) { updateProgMethod = UpdateProgress; } private void GetDirectorySizeAsync(string path) { backgroundWorker.RunWorkerAsync(path); } private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e) { DirectoryInfo di = new DirectoryInfo((string)e.Argument); di.GetTotalSize(ProgressCallback); } // Takes callbacks from the GetTotalSize() method private void ProgressCallback(float p) { // Invokes update progress bar on GUI thread: this.BeginInvoke(updateProgMethod, new object[] { p }); } // Actually updates the progress bar: private void UpdateProgress(float p) { progressBar.Value = (int)(p * (progressBar.Maximum - progressBar.Minimum)) + progressBar.Minimum; } } public static class IOExtensions { public static long GetTotalSize(this DirectoryInfo directory, Action progressCallback) { FileInfo[] files = directory.GetFiles("*.*", SearchOption.AllDirectories); long sum = 0; int countDown = 0; for (int i = 0; i < files.Length; i++) { sum += files[i].Length; countDown--; if (progressCallback != null && countDown <= 0) { countDown = 100; progressCallback((float)i / files.Length); } } return sum; } } 

在不知道文件或文件夹数量的情况下很难猜测进度!

编辑:我已经改进了一点代码。

如果在调用方法时,您不知道该方法需要多长时间或涉及多少个离散步骤,那么在执行该方法时无法显示进度条。

在我看来,进度条的目的不是提供有关何时完成任务的可靠信息。 相反,目的是让用户不要害怕并取消整个操作,因为他们认为你的程序已经锁定并且根本没有做任何事情。

由于您正在遍历目录和子目录,因此这里更简单的方法可能是在Label中显示当前目录。 这将使用户感觉到事情正在发生,如果目录全部按字母顺序排序,他们甚至可以自己测量操作的整体进度。

我会报告你已经走了多远,因为在你到达那里之前你不知道目标。 我会在每次调用时执行一次。 也许到目前为止看到的文件数和#目录数。