我已經寫了一個應用程序,將兩個文件夾同步到一起。該程序的問題在於它在複製文件時停止響應。快速搜索堆棧溢出告訴我,我需要使用稱爲後臺工作者的東西。我已經在網上閱讀了幾頁關於此的內容,但是由於我對編程很陌生,所以很難理解。我怎樣才能簡單地將所有的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