我已经写了一个应用程序,将两个文件夹同步到一起。该程序的问题在于它在复制文件时停止响应。快速搜索堆栈溢出告诉我,我需要使用称为后台工作者的东西。我已经在网上阅读了几页关于此的内容,但是由于我对编程很陌生,所以很难理解。我怎样才能简单地将所有的File.Copy(....)命令放入他们自己的后台工作器中(如果这甚至是它的工作原理)?下面是运行子过程的按钮单击事件代码和我希望在所有File.Copy行上使用后台工作程序的子过程。无法让我的头在.NET中的后台工作人员
任何帮助将大大赞赏,因为在此之后,程序会几乎完成:d
编辑
使用德维尔的意见,但是,下面我不断收到follwoing错误,我已经改变了我相应的代码:
错误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);
}
}
不要忘记考虑它对您的用户界面的影响。偶尔检查BackgroundWorker是否仍在运行(在UI线程上有一个System.Windows.Forms.Timer),以及何时完成,让用户知道UI。你会同时允许多个后台任务吗?长期来看,应该考虑如何处理后台线程中的错误并告知用户。 – 2010-04-09 14:06:31