Question

So, I'm doing a simple scan to get a list of all folders on a hard drive (c:\windows and c:\windows\system32 are considered separate entries). If I wanted to provide a progress bar for this 1-2 minute task, how would I do so? That is, I know how to make the progressbar but am not sure how to determine how much of the work for it is done.

Edit: Note that performing a prescan is NOT a solution, since this scan is only getting a list of folders and a prescan would take just as long.

Code Sample is below. It takes under 2 minutes to run clean on my system, but less than 10s to run a 2nd time due to disk access caching. I've created variations on this that are stack-based rather than recursion based.

One mechanism I've found that is probably not 100% reliable but is much faster than my scan is to pipe "dir/s/ab/b" to my program and count instances of newline. Dir does some sort of magic that does a much better job scanning my HD than my program, but I don't know what that magic is.

class Program
{
    static void recurse(string pos)
    {
        DirectoryInfo f = new DirectoryInfo(pos);
        try
        {
            foreach (DirectoryInfo x in f.GetDirectories("*"))
            {
                recurse(x.FullName);
            }
        } catch (Exception) {}
    }
    static void Main(string[] args)
    {
        recurse("c:\\");
    }
}
Was it helpful?

Solution

If you can't recurse the directory structure since that would take as long as performing the task in the first place, the best you can do is guess how many folders there are. Seriously.

Perhaps you can use an algorithm based on past history (e.g. the last time I did this there were 150 directories in total when there were 10 top-level directories, therefore a good guess would be 15 times the current number of top-level directories).

Another way to tell a user something is going to take a while (without knowing exactly how long) is to use a countdown timer. Even if you've guessed that something will take longer than it actually will (say 5 minutes when it's really a 3-minute task), at least the user knows roughly how long it's going to take. And they'll be happier when it finishes faster than they were told it would. The only bummer, of course, is if you guess wrong on the other side, i.e. if something takes longer than you thought it would. Then they're sitting there waiting for something to finish that (in their mind) should have finished already.

OTHER TIPS

If you need to make a progress bar and you can't spare the time it takes to gather accurate information, then you're not going to be able to make a perfect progress bar. With that assumption in mind, you can still make a progress bar that isn't completely inaccurate.

For example, you make a function that subdivides the progress bar depending on the number of subdirectories in the current directory. So if your root directory has 10 subdirectories, allocate 10% of the progress bar to each of those directories. Then, enter into the first subdirectory and count its subdirectories. If it has 5, allocate 20% of the first 10% of the progress bar to each of those (2% of the total progress bar). Continue like this until you reach a directory with no subdirectories, do your processing there and increase the progress bar whatever fractional amount it represents.

Each % on the progress bar won't represent the same amount of work done by the algorithm, but given your contraints I doubt you can do much better.

Just don't use it. Try something more appropriate like spinning animation or Kitts style bar: http://en.wikipedia.org/wiki/KITT.

You can do it in a few ways....a simple process that might not be 100% accurate.

Before you start, get a count of files, then use that to calculate the percentage of completion, after processing X files update the progress. Granted there is a performance cost of the lookup. Maybe just get a count of root directories, and as you traverse update the progress.

Another option might be to simply record a count of "last run" details, and use that to calculate a percentage, again, not necessarily 100% accurate, but an option.

I guess a few other things that come to mind is to simply show the user a "in progress" dialog and not even try to get a percentage. Otherwise, maybe just show the current working directory, showing that you are making progress.

I tried grabbing the stdoutput of "dir/ad/b/s c:/" and counting the number of lines. This is pretty fast. It's trustworthy enough for use in a progressbar but not trustworthy enough for use as a list of directories.

You can create a progress bar with incrementing Maximum & Value properties. If you have your Maximum property initially set at 100, on your Timer's Tick event, increment both your Maximum & Value by 1 for example so you'll have values listed below...

         Maximum    Value 
Tick1:    101          1   - 1% 
Tick2:    102          2   - 2%
Tick3:    103          3   - 3% 
TickN:    100+n        n 
Finish    100+n      100+n - 100%  --> force to fill the progress bar

You can experiment on your initial Maximum value to have the progress bar move smoother.

I used Catchwa's method. I set the progress range to 14000 because the OSes on my system have about that many dirs. When I found an empty dir, I added the fractional, weighted amount to the progress bar. The amount being based on the depth and normalized with the range. In every subtree traversal you eventually end up with an empty dir and the weight of all the empty subdirs in a dir comprise the weight of the dir, but broken into chunks. When I found a non-empty dir I stored the number of subdirs in a map. I got, using Qt:

emit findProgressBar_setRange(14000); ... if (dir.size()) { m_dirsAtDepth[++m_depth] = dir.size(); } else { qreal product = 1.00; for (int i = 1; i <= m_depth; ++i) { product *= m_dirsAtDepth[i]; } int x = qRound((1.00 / product) * 14000); emit findProgressBar_addValue(x); }

It runs pretty smooth and it's cheap. I also offer the user an accurate progress bar option where I count the total number of dirs first, which can be expensive.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top