Wednesday, 2 October 2013

How can I make GUI responsive during long iteration?

How can I make GUI responsive during long iteration?

To begin with, I'm relatively new to programming. I went through some
introductory C# training for my new job, and it's the first language I've
worked with.
I recently had a business problem that I decided to solve using C#, both
to save time (I had hoped) and to learn more C# in the process. The
business problem I mentioned was this: I had 600+ Word files that I needed
to audit. For each document, I had to make sure that...
There was no text with strike-through anywhere in the document.
Track Changes was disabled.
There were no pending changes (as in changes that were made while Track
Changes was enabled and have yet to be accepted or rejected).
There were no comments.
It would have been fastest to have my program iterate through all of the
documents, making changes as it went along. But because of the nature of
this assignment I wanted to make the changes manually, limiting the
program's use to generating a list of files (out of the 600) where changes
were necessary, and detailing what changes needed to be made for each of
those files.
So, I have a button that calls up a FolderBrowserDialog.
private void AddFolderButtonClick(object sender, EventArgs e)
{
var folderBrowser = new FolderBrowserDialog();
if (folderBrowser.ShowDialog() != DialogResult.OK)
{
return;
}
this.progressBar1.Visible = true;
this.progressBar1.Style = ProgressBarStyle.Marquee;
this.Cursor = Cursors.WaitCursor;
var args = new
List<string>(Directory.EnumerateDirectories(folderBrowser.SelectedPath));
// Get list of files in selected directory, adding to list of
directories
args.AddRange(Directory.EnumerateFiles(folderBrowser.SelectedPath));
this.displayListBox.BeginUpdate();
foreach (string path in args)
{
if (File.Exists(path))
{
// This path is a file
this.ProcessFile(Path.GetFullPath(path));
}
else if (Directory.Exists(path))
{
// This path is a directory
this.ProcessDirectory((Path.GetFullPath(path)));
}
else
{
Console.WriteLine(Resources.Finder_Invalid_File_Or_Directory,
path);
}
}
this.displayListBox.EndUpdate();
this.progressBar1.Visible = false;
this.progressBar1.Style = ProgressBarStyle.Continuous;
this.Cursor = Cursors.Default;
}
Together, the following two methods iterate through all subdirectories and
files to create a full list of all files below the top level directory
selected through the FolderBrowserDialog:
private void ProcessDirectory(string targetDirectory)
{
// Process the list of files found in the directory.
string[] fileEntries = Directory.GetFiles(targetDirectory);
foreach (string fileName in fileEntries)
{
this.ProcessFile(fileName);
}
// Recurse into subdirectories of this directory.
string[] subdirectoryEntries =
Directory.GetDirectories(targetDirectory);
foreach (string subdirectory in subdirectoryEntries)
{
this.ProcessDirectory(subdirectory);
}
}
private void ProcessFile(string path)
{
Console.WriteLine(Resources.Finder_File_Processed, path);
string fileName = Path.GetFileName(path);
if (fileName == null || fileName.StartsWith(@"~$") ||
this.selectedFilesList.Contains(path))
{
return;
}
this.selectedFilesList.Add(path);
this.filePathsCountLabel.Text = (@"Count: " +
this.selectedFilesList.Count);
this.displayListBox.Items.Add(path);
}
Once all this code has run, I get a full list of documents. I click a
button and the program does what it's supposed to from here on out. Okay,
cool. I mentioned before that half of the reason I chose to use C# to
solve this was for the sake of learning. At this point I've got everything
I need but what I really want to know is how can I implement threading to
make the GUI responsive while the list of files is being generated? I've
looked through several examples. They made sense. For some reason I just
can't get my head around it for this application though. How can I make
the whole process of processing subdirectories and files happen without
locking up the GUI?

No comments:

Post a Comment