I have wrote an application that syncs two folders together. The problem with the program is that it stops responding whilst copying files. A quick search of stack-overflow told me I need to use something called a background worker. I have read a few pages on the net about this but find it really hard to understand as I'm pretty new to programming. How can I simply put all of the File.Copy(....) commands into their own background worker (if that's even how it works)? Below is the code for the button click event that runs the sub procedure and the sub procedure I wish to use a background worker on all the File.Copy lines.
Any help will be greatly appreciated as after this the program will pretty much be finished :D
EDIT
Using the advice of Veer below I have changed my code accordingly however I keep getting the follwoing errors:
Error CS1061: Type Gtk.ProgressBar' does not contain a definition for
InvokeRequired' and no extension method InvokeRequired' of type
Gtk.ProgressBar' could be found (are you missing a using directive or an assembly reference?) (CS1061) (Sync-GUI v2)
Error CS1061: Type Gtk.ProgressBar' does not contain a definition for
BeginInvoke' and no extension method BeginInvoke' of type
Gtk.ProgressBar' could be found (are you missing a using directive or an assembly reference?) (CS1061) (Sync-GUI v2)
Below is my code.
Button Click Event:
protected virtual void OnBtnSyncClicked (object sender, System.EventArgs e)
{
//sets progress bar to 0
prgProgressBar.Fraction = 0;
//resets values used by progressbar
dblCurrentStatus = 0;
dblFolderSize = 0;
//tests if user has entered the same folder for both target and destination
if (fchFolder1.CurrentFolder == fchFolder2.CurrentFolder)
{
//creates message box
MessageDialog msdSame = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.Close, "You cannot sync two folders that are the same");
//sets message box title
msdSame.Title="Error";
//sets respone type
ResponseType response = (ResponseType) msdSame.Run();
//if user clicks on close button or closes window then close message box
if (response == ResponseType.Close || response == ResponseType.DeleteEvent) {
msdSame.Destroy();
}
return;
}
//tests if user has entered a target folder that is an extension of the destination folder
// or if user has entered a desatination folder that is an extension of the target folder
if (fchFolder1.CurrentFolder.StartsWith(fchFolder2.CurrentFolder) || fchFolder2.CurrentFolder.StartsWith(fchFolder1.CurrentFolder))
{
//creates message box
MessageDialog msdContains = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.Close, "You cannot sync a folder with one of its parent folders");
//sets message box title
msdContains.Title="Error";
//sets respone type and runs message box
ResponseType response = (ResponseType) msdContains.Run();
//if user clicks on close button or closes window then close message box
if (response == ResponseType.Close || response == ResponseType.DeleteEvent)
{
msdContains.Destroy();
}
return;
}
//creates background worker
BackgroundWorker bwBackgroundWorker = new BackgroundWorker();
bwBackgroundWorker.DoWork += new DoWorkEventHandler(bwBackgroundWorkerDoWorkFolder1);
//starts background worker
bwBackgroundWorker.RunWorkerAsync();
//informs user process is complete
prgProgressBar.Text = "Finished";
}
Background Worker Do Work Event:
private void bwBackgroundWorkerDoWorkFolder1 (object sender, DoWorkEventArgs e)
{
//Gets total file size of folder 1
TotalFileSizeFolder1(fchFolder1.CurrentFolder);
//Syncs folder 1
SyncFolder1(fchFolder1.CurrentFolder, fchFolder2.CurrentFolder);
}
TotalFileSizeFolder1 Sub Routine:
protected void TotalFileSizeFolder1 (string strCurrentDirectory)
{
//inform user that file sizes are being gathered
if (prgProgressBar.InvokeRequired)
{
prgProgressBar.BeginInvoke(new MethodInvoker(delegate {prgProgressBar.Text="Getting total size of " + strCurrentDirectory;}));
}
//string array of all the directories in directory
string[] staAllDirectories = Directory.GetDirectories(strCurrentDirectory);
//string array of all the files in directory
string[] staAllFiles = Directory.GetFiles(strCurrentDirectory);
foreach (string strFile in staAllFiles)
{
//saves new file info called FileSize
FileInfo FileSize = new FileInfo(strFile);
//adds file size
dblFolderSize = dblFolderSize + FileSize.Length;
//pulses progress bar to indicate some movement
if (prgProgressBar.InvokeRequired)
{
prgProgressBar.BeginInvoke(new MethodInvoker(delegate {prgProgressBar.Pulse();}));
}
}
foreach (string strDirectory in staAllDirectories)
{
TotalFileSize(strDirectory);
}
//delete text from progress bar
if (prgProgressBar.InvokeRequired)
{
prgProgressBar.BeginInvoke(new MethodInvoker(delegate {prgProgressBar.Text="";}));
}
}
SyncFolder1 Sub Routine:
protected void SyncFolder1 (string strFolder1, string strFolder2)
{
//string array of all the directories in directory
string[] staAllDirectories = Directory.GetDirectories(strFolder1);
//string array of all the files in directory
string[] staAllFiles = Directory.GetFiles(strFolder1);
//loop over each file in directory
foreach (string strFile in staAllFiles)
{
//string of just the file's name and not its path
string strFileName = System.IO.Path.GetFileName(strFile);
//string containing directory in target folder
string strDirectoryInsideFolder1 = System.IO.Path.GetDirectoryName(strFile).Substring(strFolder1.Length);
//inform user as to what file is being copied
if (prgProgressBar.InvokeRequired)
{
prgProgressBar.BeginInvoke(new MethodInvoker(delegate {prgProgressBar.Text="Syncing " + strFile;}));
}
//tests if file does not exist in destination folder
if (!File.Exists(fchFolder2.CurrentFolder + "/" + strDirectoryInsideFolder1 + "/" + strFileName))
{
//if file does not exist copy it to destination folder, the true below means overwrite if file already exists
File.Copy (strFile, strFolder2 + "/" + strDirectoryInsideFolder1 + "/" + strFileName, true);
}
//tests if file does exist in destination folder
if (File.Exists(strFolder2 + "/" + strDirectoryInsideFolder1 + "/" + strFileName))
{
//long (number) that contains date of last write time of target file
long lngFolder1FileDate = File.GetLastWriteTime(strFile).ToFileTime();
//long (number) that contains date of last write time of destination file
long lngFolder2FileDate = File.GetLastWriteTime(strFolder2 + "/" + strDirectoryInsideFolder1 + "/" + strFileName).ToFileTime();
//tests if target file is newer than destination file
if (lngFolder1FileDate > lngFolder2FileDate)
{
//if it is newer then copy file from target folder to destination folder
File.Copy (strFile, strFolder2 + "/" + strDirectoryInsideFolder1 + "/" + strFileName, true);
}
}
//gets current file size
FileInfo FileSize = new FileInfo(strFile);
//sets file's filesize to dblCurrentStatus and adds it to current total of files
dblCurrentStatus = dblCurrentStatus + FileSize.Length;
double dblPercentage = dblCurrentStatus/dblFolderSize;
if (prgProgressBar.InvokeRequired)
{
prgProgressBar.BeginInvoke(new MethodInvoker(delegate {prgProgressBar.Fraction = dblPercentage;}));
}
}
//loop over each folder in target folder
foreach (string strDirectory in staAllDirectories)
{
//string containing directories inside target folder but not any higher directories
string strDirectoryInsideFolder1 = strDirectory.Substring(strFolder1.Length);
//tests if directory does not exist inside destination folder
if (!Directory.Exists(strFolder2 + "/" + strDirectoryInsideFolder1))
{
//it directory does not exisit create it
Directory.CreateDirectory(strFolder2 + "/" + strDirectoryInsideFolder1);
}
//run sync on all files in directory
SyncFolders(strDirectory, strFolder2);
}
}