C# 每次单击按钮都会导致后台工作人员运行复制文件的时间

C# 每次单击按钮都会导致后台工作人员运行复制文件的时间,c#,progress-bar,backgroundworker,C#,Progress Bar,Backgroundworker,我有一个windows应用程序(C#),其中我将一些文件从目录(递归)复制到用户从UI选择的驱动器 它工作得很好-所有文件都移动到相应的驱动器 但这个过程会随着按钮的点击次数而增加 即 用户单击“备份桌面”,它将运行到100%完成 用户然后单击“备份收藏夹”,它将运行两次,100%完成 用户然后点击任何其他按钮,它运行到100%完成,三次 我无法在下面的代码中找到它被调用的位置,以增加进程完成的次数 我肯定我在什么地方错过了它——我只是不知道在哪里 我使用了一个进度条,这样我就可以让用户以图

我有一个windows应用程序(C#),其中我将一些文件从目录(递归)复制到用户从UI选择的驱动器

它工作得很好-所有文件都移动到相应的驱动器

但这个过程会随着按钮的点击次数而增加

  • 用户单击“备份桌面”,它将运行到100%完成
  • 用户然后单击“备份收藏夹”,它将运行两次,100%完成
  • 用户然后点击任何其他按钮,它运行到100%完成,三次
我无法在下面的代码中找到它被调用的位置,以增加进程完成的次数

我肯定我在什么地方错过了它——我只是不知道在哪里

我使用了一个进度条,这样我就可以让用户以图形的方式知道正在发生什么——它按预期运行

/*
 * ***** *
 * Copy all directories and files recursively
 * ***** *
*/
public void CopyFilesRecursively(DirectoryInfo source, DirectoryInfo target)
{
    foreach (DirectoryInfo dir in source.GetDirectories())
    {
        if ((dir.Name == "My Music") || (dir.Name == "My Pictures") || (dir.Name == "My Videos"))
        {
            //do nothing with it since it is just a system link we cannot access
        }
        else
        {
            CopyFilesRecursively(dir, target.CreateSubdirectory(dir.Name));
        }
    }
    foreach (FileInfo file in source.GetFiles())
        file.CopyTo(Path.Combine(target.FullName, file.Name), true);
}

/* 
 * *****
 * PROGRESS BAR METHODS *
 * *****
*/
void bgWorker_DoWork(object sender, DoWorkEventArgs e)
{
    string buttonSender = clickedButton; //Desktop, Documents, etc.
    switch (buttonSender) {
        case "Desktop":
            destinationLocation = selectedDrive + "Backups-" + DateTime.Now.Month.ToString() + "-" + DateTime.Now.Year.ToString() + "\\Desktop\\";
            string desktopFolder = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
            source = new DirectoryInfo(desktopFolder);
            break;
        case "Documents":
            destinationLocation = selectedDrive + "Backups-" + DateTime.Now.Month.ToString() + "-" + DateTime.Now.Year.ToString() + "\\Documents\\";
            string documentsFolder = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            source = new DirectoryInfo(documentsFolder);
            break;
        case "Favorites":
            destinationLocation = selectedDrive + "Backups-" + DateTime.Now.Month.ToString() + "-" + DateTime.Now.Year.ToString() + "\\Favorites\\";
            string favoritesFolder = Environment.GetFolderPath(Environment.SpecialFolder.Favorites);
            source = new DirectoryInfo(favoritesFolder);
            break;
        default :

            break;
    }

    DirectoryInfo target = new DirectoryInfo(destinationLocation);
    fileCount = source.GetFiles("*", SearchOption.AllDirectories).Length;
    totalFileCount = fileCount;
    int total = totalFileCount; //some number (this is your variable to change)!!
    for (int i = 0; i <= total; i++) //some number (total)
    {
        System.Threading.Thread.Sleep(100);
        int percents = (i * 100) / total;
        bgWorker.ReportProgress(percents, i);
        //2 arguments:
        //1. procenteges (from 0 t0 100) - i do a calcumation 
        //2. some current value!
    }
    if (!Directory.Exists(destinationLocation))
    {
        Directory.CreateDirectory(destinationLocation);
    }
    CopyFilesRecursively(source, target);
}

void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    essentialItemsProgressBar.Visible = true;
    essentialItemsProgressBar.Value = e.ProgressPercentage;

    int percent = (int)(((double)(essentialItemsProgressBar.Value - essentialItemsProgressBar.Minimum) /
    (double)(essentialItemsProgressBar.Maximum - essentialItemsProgressBar.Minimum)) * 100);
    using (Graphics gr = essentialItemsProgressBar.CreateGraphics())
    {
        gr.DrawString(percent.ToString() + "%",
            SystemFonts.DefaultFont,
            Brushes.Black,
            new PointF(essentialItemsProgressBar.Width / 2 - (gr.MeasureString(percent.ToString() + "%",
                SystemFonts.DefaultFont).Width / 2.0F),
            essentialItemsProgressBar.Height / 2 - (gr.MeasureString(percent.ToString() + "%",
                SystemFonts.DefaultFont).Height / 2.0F)));
    }

    essentialItemsProgressLabel.Visible = true;
    essentialItemsProgressLabel.Text = String.Format("Progress: {0} % - All {1} Files Transferred", e.ProgressPercentage, clickedButton);
    //essentialItemsProgressLabel.Text = String.Format("Total items transfered: {0}", e.UserState);
}

void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    //do the code when bgv completes its work
    essentialItemsProgressBar.Visible = false;
}
/* 
 * *****
 * END OF PROGRESS BAR METHODS *
 * *****
*/
/*
 * ***** DESKTOP BACKUP ***** *
*/
private void backupDesktopButton_Click(object sender, EventArgs e)
{
    clickedButton = ((Button)sender).Text.ToString();
    selectedDrive = backupDriveCombo.SelectedItem.ToString();
    bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
    bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
    bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
    bgWorker.WorkerReportsProgress = true;
    bgWorker.RunWorkerAsync();
}
/*
 * ***** DOCUMENTS BACKUP ***** *
*/
private void backupDocumentsButton_Click(object sender, EventArgs e)
{
    clickedButton = ((Button)sender).Text.ToString();
    selectedDrive = backupDriveCombo.SelectedItem.ToString();
    bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
    bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
    bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
    bgWorker.WorkerReportsProgress = true;
    bgWorker.RunWorkerAsync();
}
/*
* ***** *
*递归复制所有目录和文件
* ***** *
*/
以递归方式公开无效复制文件(DirectoryInfo源、DirectoryInfo目标)
{
foreach(source.GetDirectories()中的DirectoryInfo目录)
{
如果((dir.Name==“我的音乐”)| |(dir.Name==“我的图片”)| |(dir.Name==“我的视频”))
{
//不要使用它,因为它只是一个我们无法访问的系统链接
}
其他的
{
以递归方式复制文件(dir,target.CreateSubdirectory(dir.Name));
}
}
foreach(source.GetFiles()中的FileInfo文件)
CopyTo(Path.Combine(target.FullName,file.Name),true);
}
/* 
* *****
*进度条方法*
* *****
*/
void bgWorker\u DoWork(对象发送方,DoWorkEventArgs e)
{
string buttonSender=clickedButton;//桌面、文档等。
开关(按钮下){
案例“桌面”:
destinationLocation=selectedDrive+“Backups-”+DateTime.Now.Month.ToString()+“-”+DateTime.Now.Year.ToString()+“\\Desktop\\”;
字符串desktopFolder=Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
source=新目录信息(desktopFolder);
打破
案例“文件”:
destinationLocation=selectedDrive+“Backups-”+DateTime.Now.Month.ToString()+“-”+DateTime.Now.Year.ToString()+“\\Documents\\”;
string documentsFolder=Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
source=新目录信息(documentsFolder);
打破
案例“收藏夹”:
destinationLocation=selectedDrive+“Backups-”+DateTime.Now.Month.ToString()+“-”+DateTime.Now.Year.ToString()+“\\Favorites\\”;
字符串favoritesFolder=Environment.GetFolderPath(Environment.SpecialFolder.Favorites);
source=新目录信息(favoritesFolder);
打破
违约:
打破
}
DirectoryInfo目标=新的DirectoryInfo(destinationLocation);
fileCount=source.GetFiles(“*”,SearchOption.AllDirectories).Length;
totalFileCount=文件计数;
int total=totalFileCount;//一些数字(这是要更改的变量)!!

对于(int i=0;i问题出现在这一行中(在
备份文档按钮中单击()
方法):

您应该只执行一次(即在创建bgWorker时),但每次单击按钮时都执行此操作。第一次单击后,您将向按钮添加一个处理程序,第二次单击后,您将再添加一个处理程序-将调用两次

您应该更改代码:

private void backupDocumentsButton_Click(object sender, EventArgs e)
{
    clickedButton = ((Button)sender).Text.ToString();
    selectedDrive = backupDriveCombo.SelectedItem.ToString();
    // without these lines
    // bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork); 
    // bgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_ProgressChanged);
    // bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_RunWorkerCompleted);
    bgWorker.WorkerReportsProgress = true;
    bgWorker.RunWorkerAsync();
}
您应该在创建
bgWorker
后添加行,即:

BackgroundWorker bgWorker = new BackgroundWorker();
bgWorker.DoWork += bgWorker_DoWork;
bgWorker.ProgressChanged += bgWorker_ProgressChanged;
bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted;

您应该只添加一次事件处理程序。

。因为您在每次单击中将事件处理程序添加到
DoWork
?我应该如何更好地处理它?“我应该如何更好地处理它?”--只是不要这样做。请配置
BackgroundWorker
一次(如果将其作为组件添加到表单中,则可以使用设计器中的属性窗口设置事件处理程序),或每次运行时都创建一个新的
BackgroundWorker
。但无论您做什么,不要每次运行worker时都在同一对象的同一事件中添加一个新的处理程序。有关确切问题的描述和解决方案,请参阅标记的重复。另请参阅、和其他文章,如他们在com中所说的相同内容但是这很好地澄清了这一点,我可以很容易地看到/理解。谢谢!这很有效。我会在几分钟内接受。
BackgroundWorker bgWorker = new BackgroundWorker();
bgWorker.DoWork += bgWorker_DoWork;
bgWorker.ProgressChanged += bgWorker_ProgressChanged;
bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted;