Reputation: 951
It's my first time using progress bars in C#. My code is copying some files and I would like to display the progress via a progress bar.
The thing I don't like about my code is that I have to go through all files to set the maximum of the bar... and later I go through that same process again to copy the files.
I just can't figure out a way to ensure a fluent progress in the bar without doeing that. I first have to know the max right? Or is there a trick?
Code looks like that:
Setting up the max:
private static void setProgressBar(List<Source> sources, List<Destination> destinations)
{
progress.Value = 0;
progress.Maximum = 0;
foreach (var source in sources)
{
progress.Maximum += System.IO.Directory.GetDirectories(source.directory, "*",
SearchOption.AllDirectories).Count() * destinations.Count +
System.IO.Directory.GetFiles(source.directory, "*.*", SearchOption.AllDirectories).Count() *
destinations.Count;
}
Copying the files:
public static void CopyData(List<Source> sources, List<Destination> destinations, RichTextBox box, ProgressBar bar)
{
log = box;
progress = bar;
setProgressBar(sources, destinations);
foreach (var source in sources)
{
foreach (var dirPath in System.IO.Directory.GetDirectories(source.directory, "*",
SearchOption.AllDirectories))
{
foreach (var destination in destinations)
{
logger(dirPath);
System.IO.Directory.CreateDirectory(dirPath.Replace(source.directory, destination.directory));
}
}
foreach (var newPath in System.IO.Directory.GetFiles(source.directory, "*.*", SearchOption.AllDirectories))
{
foreach (var destination in destinations)
{
logger(newPath);
File.Copy(newPath, newPath.Replace(source.directory, destination.directory), true);
}
}
}
}
Increment the progress bar:
private static void logger(string output) { log.Text += "Copy: " + output + System.Environment.NewLine; log.SelectionStart = log.Text.Length; log.ScrollToCaret(); progress.Increment(1); }
So I'm running the same code twice... and I don't like that :)
Upvotes: 2
Views: 990
Reputation: 518
I see two Errors in here: you never set your progressbar's value in the CopyData method and the second one is: your CopyData method will cause your UI to freeze until the method is done (and the progressbar will jump from 0 to 100% at that time).
You can put your CopyData method in a BackgroundWorker and call ReportProgressand set the new Value of your bar in the ReportProgress-event.
Here is an example of how it could be done. Instead of static void Main(..)
call the worker from where you would start your CopyData-method
static void Main(string[] args)
{
System.ComponentModel.BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();
worker.ProgressChanged += Worker_ProgressChanged;
worker.DoWork += Worker_DoWork;
//Do work
worker.RunWorkerAsync();
}
private static void Worker_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
{
//Get Values
var source = null;
var destinations = null;
//CopyData Method
setProgressBar(sources, destinations);
foreach (var source in sources)
{
foreach (var dirPath in System.IO.Directory.GetDirectories(source.directory, "*", SearchOption.AllDirectories))
{
foreach (var destination in destinations)
{
logger(dirPath);
System.IO.Directory.CreateDirectory(dirPath.Replace(source.directory, destination.directory));
//Increase Value by 1
(sender as System.ComponentModel.BackgroundWorker).ReportProgress(1);
}
}
foreach (var newPath in System.IO.Directory.GetFiles(source.directory, "*.*", SearchOption.AllDirectories))
{
foreach (var destination in destinations)
{
logger(newPath);
File.Copy(newPath, newPath.Replace(source.directory, destination.directory), true);
//Increase Value by 1
(sender as System.ComponentModel.BackgroundWorker).ReportProgress(1);
}
}
}
}
private static void Worker_ProgressChanged(object sender, System.ComponentModel.ProgressChangedEventArgs e)
{
if (e.ProgressPercentage == 1)
{
//If Value gets higher than Maximum it will cause an Exception
if (progress.Value < progress.Maximum)
progress.Value += 1;
}
}
private static void setProgressBar(List sources, List destinations)
{
progress.Value = 0;
progress.Maximum = 0;
foreach (var source in sources)
{
foreach (var dirPath in System.IO.Directory.GetDirectories(source.directory, "*", SearchOption.AllDirectories))
{
//Simplified
progress.Maximum += destinations.Count;
}
foreach (var newPath in System.IO.Directory.GetFiles(source.directory, "*.*", SearchOption.AllDirectories))
{
//Simplified
progress.Maximum += destinations.Count;
}
}
}
Upvotes: 1