EDN Admin
Well-known member
The following code copies the contents of one folder to another on a background worker thread.
In the ProgressChanged event, I use the ProgressPercentage to determine what to do, and the UserState contains a string. Two of the possibilities go to a class called Common that has a reference to the UI class in p.
The backgroundworker itself is the UI control, not the class.
There is no blocking of the UI. When the backgroundworker is called, control is immediately returned to the UI (buttons are disabled because this program is copied along with other stuff, then executed from the new, known location as this one finishes).
The problem is that the status label doesnt get updated as it should. If a long copy follows an update, it just sits there even though the richtextbox got updated. For example, file a in folder b is displayed on the status bar. File c
in folder d is large and is now being copied. Folder d is shown in the richtextbox, but file a is still showing on the status bar. Any idea how to fix this? Code follows..
<pre class="prettyprint // In GUI
#region Copy Installation
/// <summary>
/// Copies the installation and returns to GUI
/// </summary>
internal void CopySoftware()
{
Buttons(false); // Disable buttons
// Copy the installation files on first run
if (!var.IsCopied && !var.IsRestart)
bgWorker.RunWorkerAsync();
}
#endregion
#region Background Worker for installation copy
/// <summary>
/// Handles progress from the background worker
/// </summary>
/// <param name="sender worker</param>
/// <param name="e arguments</param>
/// <remarks>
/// Note: e.ProgreaaPercentage contains the progress type
/// e.UserState contains text
/// </remarks>
internal void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
switch (e.ProgressPercentage) {
case var.display:
Common.AddText(e.UserState.ToString());
break;
case var.status:
Common.Status(e.UserState.ToString());
break;
case var.log:
Common.log(e.UserState.ToString());
break;
}
}
/// <summary>
/// Does the background copy
/// </summary>
/// <param name="sender worker</param>
/// <param name="e arguments</param>
internal void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
// Copy installation files if necessary
worker.ReportProgress(var.display, "fJLfCopying Software Installationn");
Common.CopyAll(var.CDDirectory, var.SoftwareDir, worker, e);
worker.ReportProgress(var.display, "Donen");
Directory.SetCurrentDirectory(var.PathSoftware);
}
/// <summary>
/// Called when the background worker finishes
/// </summary>
/// <param name="sender </param>
/// <param name="e </param>
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
StartInstall();
}
#endregion
// In Common class
#region Copy All
/// <summary>
/// Copies all files and subdirectories from the source directory to the target
/// </summary>
/// <param name="source Source pathname</param>
/// <param name="target Target pathname</param>
[DebuggerStepThrough]
internal static void CopyAll(DirectoryInfo source, DirectoryInfo target,
BackgroundWorker worker, DoWorkEventArgs e)
{
string part; // Directory name
int x; // General indes
// Check if the directory exists, if not, create it
MakeDirectory(target.FullName);
// Show copying messages to the user
if (target.FullName == @"C:Software") // Is this the root?
worker.ReportProgress(var.display, "tCopying Installer Filesn"); // Yes, copying installer files
else {
x = target.FullName.IndexOf("\", 12); // Extract first directory after root
if (x < 0)
part = target.FullName.Substring(12);
else
part = target.FullName.Substring(12, x - 12);
if (part != var.last) { // Different from last directory?
worker.ReportProgress(var.display, "tCopying " + part + "n"); // Yes, print it
var.last = part; // Save last used
}
}
// Copy each file into its new directory
x = 0; // Set up for copy counter
foreach (FileInfo fi in source.GetFiles()) {
worker.ReportProgress(var.log, string.Format("Copying File {0} to {1}n",
Path.GetFileName(fi.FullName), Path.GetFullPath(target.Name)));
if (File.Exists(target + "\" + fi.Name))
Common.DeleteFile(target + "\" + fi.Name);
fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
worker.ReportProgress(var.status, "Copying: " + fi.Name);
}
// Copy each directory using recursion
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories()) {
DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir, worker, e);
}
}
#endregion
#region Update Status Message
/// <Summary>
/// Updates the status bar message
/// </Summary>
/// <param name="text Message</param>
internal static void Status(string text)
{
p.lblStatus.Text = text;
}
#endregion [/code]
<br/>
View the full article
In the ProgressChanged event, I use the ProgressPercentage to determine what to do, and the UserState contains a string. Two of the possibilities go to a class called Common that has a reference to the UI class in p.
The backgroundworker itself is the UI control, not the class.
There is no blocking of the UI. When the backgroundworker is called, control is immediately returned to the UI (buttons are disabled because this program is copied along with other stuff, then executed from the new, known location as this one finishes).
The problem is that the status label doesnt get updated as it should. If a long copy follows an update, it just sits there even though the richtextbox got updated. For example, file a in folder b is displayed on the status bar. File c
in folder d is large and is now being copied. Folder d is shown in the richtextbox, but file a is still showing on the status bar. Any idea how to fix this? Code follows..
<pre class="prettyprint // In GUI
#region Copy Installation
/// <summary>
/// Copies the installation and returns to GUI
/// </summary>
internal void CopySoftware()
{
Buttons(false); // Disable buttons
// Copy the installation files on first run
if (!var.IsCopied && !var.IsRestart)
bgWorker.RunWorkerAsync();
}
#endregion
#region Background Worker for installation copy
/// <summary>
/// Handles progress from the background worker
/// </summary>
/// <param name="sender worker</param>
/// <param name="e arguments</param>
/// <remarks>
/// Note: e.ProgreaaPercentage contains the progress type
/// e.UserState contains text
/// </remarks>
internal void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
switch (e.ProgressPercentage) {
case var.display:
Common.AddText(e.UserState.ToString());
break;
case var.status:
Common.Status(e.UserState.ToString());
break;
case var.log:
Common.log(e.UserState.ToString());
break;
}
}
/// <summary>
/// Does the background copy
/// </summary>
/// <param name="sender worker</param>
/// <param name="e arguments</param>
internal void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
// Copy installation files if necessary
worker.ReportProgress(var.display, "fJLfCopying Software Installationn");
Common.CopyAll(var.CDDirectory, var.SoftwareDir, worker, e);
worker.ReportProgress(var.display, "Donen");
Directory.SetCurrentDirectory(var.PathSoftware);
}
/// <summary>
/// Called when the background worker finishes
/// </summary>
/// <param name="sender </param>
/// <param name="e </param>
private void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
StartInstall();
}
#endregion
// In Common class
#region Copy All
/// <summary>
/// Copies all files and subdirectories from the source directory to the target
/// </summary>
/// <param name="source Source pathname</param>
/// <param name="target Target pathname</param>
[DebuggerStepThrough]
internal static void CopyAll(DirectoryInfo source, DirectoryInfo target,
BackgroundWorker worker, DoWorkEventArgs e)
{
string part; // Directory name
int x; // General indes
// Check if the directory exists, if not, create it
MakeDirectory(target.FullName);
// Show copying messages to the user
if (target.FullName == @"C:Software") // Is this the root?
worker.ReportProgress(var.display, "tCopying Installer Filesn"); // Yes, copying installer files
else {
x = target.FullName.IndexOf("\", 12); // Extract first directory after root
if (x < 0)
part = target.FullName.Substring(12);
else
part = target.FullName.Substring(12, x - 12);
if (part != var.last) { // Different from last directory?
worker.ReportProgress(var.display, "tCopying " + part + "n"); // Yes, print it
var.last = part; // Save last used
}
}
// Copy each file into its new directory
x = 0; // Set up for copy counter
foreach (FileInfo fi in source.GetFiles()) {
worker.ReportProgress(var.log, string.Format("Copying File {0} to {1}n",
Path.GetFileName(fi.FullName), Path.GetFullPath(target.Name)));
if (File.Exists(target + "\" + fi.Name))
Common.DeleteFile(target + "\" + fi.Name);
fi.CopyTo(Path.Combine(target.ToString(), fi.Name), true);
worker.ReportProgress(var.status, "Copying: " + fi.Name);
}
// Copy each directory using recursion
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories()) {
DirectoryInfo nextTargetSubDir = target.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir, worker, e);
}
}
#endregion
#region Update Status Message
/// <Summary>
/// Updates the status bar message
/// </Summary>
/// <param name="text Message</param>
internal static void Status(string text)
{
p.lblStatus.Text = text;
}
#endregion [/code]
<br/>
View the full article