Hey,

I'm having a bit of trouble with progress bars and background workers and want to try and solve this with the simplest solution

What I am doing is reading the contents of a specific directory, I am then displaying in a list box all the folder names so that a user can click on them for further functionality

What I want to do, Is have a progress bar run whilst it is adding the folders to the list box but I am not sure how I can do it..

Is anyone able to help me out?

Thanks

Dan
_____
C# - Visual Studio 2010

Dani AI

Generated

Short version: do the directory work off the UI thread and marshal only UI updates back. For VS2010 the easiest built-in tool is BackgroundWorker; for modern code prefer Task + async/await + IProgress<T>. As pointed out, a separate full count can be almost as expensive as reading the names, so pick one of two patterns depending on size: (A) small/medium sets — do one enumeration to a list, get its Count, then show a determinate progress (percent); (B) very large or unknown sets — use an indeterminate/Marquee bar and show the current folder name instead.

Example (BackgroundWorker, determinate percent):

void StartScan(string path)
{
    progressBar1.Style = ProgressBarStyle.Blocks;
    progressBar1.Minimum = 0;
    progressBar1.Maximum = 100;

    var bw = new BackgroundWorker { WorkerReportsProgress = true, WorkerSupportsCancellation = true };

    bw.DoWork += (s,e) =>
    {
        var worker = (BackgroundWorker)s;
        var dirs = Directory.EnumerateDirectories(path, "*", SearchOption.TopDirectoryOnly).ToList(); // single enumeration
        int total = dirs.Count;
        for (int i = 0; i < total; i++)
        {
            if (worker.CancellationPending) { e.Cancel = true; return; }
            int percent = (i + 1) * 100 / Math.Max(1, total);
            worker.ReportProgress(percent, dirs[i]);
        }
    };

    bw.ProgressChanged += (s,e) =>
    {
        listBox1.BeginUpdate();
        listBox1.Items.Add((string)e.UserState);
        listBox1.EndUpdate();
        progressBar1.Value = e.ProgressPercentage;
    };

    bw.RunWorkerAsync();
}

Practical tips: use Directory.EnumerateDirectories to avoid huge arrays, batch updates (buffer and AddRange) if thousands of items, and provide cancellation and IO-exception handling inside DoWork. If you use raw Threads/Task without BackgroundWorker, follow and marshal UI calls with Control.Invoke/BeginInvoke or use IProgress<T> so UI updates happen on the UI thread. For extremely large lists, consider a virtualized ListView or paging rather than adding tens of thousands of items to a ListBox.

Recommended Answers

All 3 Replies

Calculating how many files are in a directory structure (the max of the progress bar) would take pretty much just as much time as loading in the directory structure (which isn't very long with System.IO.Directory.GetDirectories()).

Basically the time it takes to count the directories is almost identical to loading all of the directory strings into an array. So unless you want this operation to take twice as long, I would just use a Marquee progress bar to let the user know the pc is busy. How are you loading in these directory names?

If there is a loop and you try to change ProgressBar value from this loop you have to check is your ProgressBar in the same thread of loop is working. (Use InvokeRequired and if it is true Invoke the method)

I recommend you dont change the value of a ProgressBar or any other controls within a thread. Instead rise an custom event.

Try pInvoke and FindFirst/FindNext for adding files into list.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.