Я написал приложение, которое синхронизирует две папки вместе. Проблема с программой заключается в том, что она перестает отвечать при копировании файлов. Быстрый поиск переполнения стека показал мне, что мне нужно использовать то, что называется фоновым рабочим. Я прочитал об этом несколько страниц в сети, но мне очень трудно это понять, так как я довольно новичок в программировании. Как я могу просто поместить все команды File.Copy (....) в их собственный фоновый рабочий (если это даже так, как это работает)? Ниже приведен код события нажатия кнопки, запускающего подпроцедуру, и подпроцедуру, которую я хочу использовать в качестве рабочего фона для всех строк File.Copy.
Любая помощь будет принята с благодарностью, так как после этого программа будет в значительной степени завершена: D
EDIT
Следуя совету Вира, я изменил свой код соответствующим образом, однако продолжаю получать следующие ошибки:
Ошибка CS1061: введите Gtk.ProgressBar' does not contain a definition for
InvokeRequired 'и метод расширения не найден InvokeRequired' of type
Gtk.ProgressBar' может быть найдено (отсутствует директива using или ссылка на сборку?) (CS1061) (Sync-GUI v2)
Ошибка CS1061: введите Gtk.ProgressBar' does not contain a definition for
BeginInvoke 'и метод расширения не найден BeginInvoke' of type
Gtk.ProgressBar' может быть найден (отсутствует директива using или ссылка на сборку?) (CS1061) (Sync-GUI v2)
Ниже мой код.
Событие нажатия кнопки:
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";
}
Событие фонового рабочего дел:
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:
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:
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);
}
}