C# 后台工作人员只做部分工作

C# 后台工作人员只做部分工作,c#,.net,backgroundworker,C#,.net,Backgroundworker,这件事把我难住了。我有一个简单的实用工具来帮助企业安装软件。一个组件备份用户当前计算机上的AppData文件,并将其保存到桌面上的文件夹中: private void backupButton_Click(object sender, EventArgs e) { backgroundBackup.RunWorkerAsync(); } private void backgroundBackup_DoWork(object sender, DoWorkEventArgs e) {

这件事把我难住了。我有一个简单的实用工具来帮助企业安装软件。一个组件备份用户当前计算机上的AppData文件,并将其保存到桌面上的文件夹中:

private void backupButton_Click(object sender, EventArgs e)
{
    backgroundBackup.RunWorkerAsync();
}


private void backgroundBackup_DoWork(object sender, DoWorkEventArgs e)
{
    ...
}

private static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
    ...
}

// I removed the message boxes from DoWork, and added a RunWorkerCompleted event, 
// but neither the confirmation nor the error messgae box from RunWorkerCompleted are shown.

private void backgroundBackup_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    ...
}
这是可行的,但不会产生预期的结果。我将此操作放在后台线程上,因为每个用户备份的总文件大小可能接近1 gb或2 gb。每次运行此操作时,都会将目标中的部分(但不是全部)文件和文件夹复制到目标,并且每次复制的文件夹都会有所不同。有时只复制少数文件和文件夹,有时几乎复制所有内容,但从未复制整个目标。如果将此操作放在一个简单的控制台应用程序中,它每次都会工作。关于BackgroundWorker类,我是否需要了解导致它不能完成DoWork方法中的所有工作

编辑:

我想我可能把BackgroundWorker类的问题复杂化了。我和一位同事谈过,他们建议用一种简单的方法创建一个新线程来处理一个可能很长的过程:

    private void backupButton_Click(object sender, EventArgs e)
    {
        Thread backupThread = new Thread(backupThreadJob);
        backupThread.Start();      
    }

    private void backupThreadJob()
    {
        try
        {
            //copy files and stuff
        }

        catch(Exception ex)
        {
            MessageBox.Show("Error: " + ex.Message);
        }
    }

这让我的工作完成了;我尝试使用BackgroundWorker时失败了,并且始终无法理解为什么只复制了一些文件。谢谢大家的帮助

这不是一个完整的答案。但我可以想象以下情况与问题有关:

请记住,
BackgroundWorker
在另一个非UI线程上执行您的
DoWork
方法,因此调用
MessageBox.Show
不是一个好主意。只有在UI(“前台”)线程上运行时,才应执行UI操作:

必须小心不要操纵DoWork事件处理程序中的任何用户界面对象。相反,通过ProgressChanged和RunWorkerCompleted事件与用户界面通信。 -


我可以想象,如果您的方法中的某个地方发生异常,并且您希望在
catch
块中显示一个消息框,那么此调用将触发另一个异常,而该异常不会得到处理。。。因此,您的方法会过早中止。

下面的示例显示您可以从后台线程调用消息框。Show是一个静态方法调用,可以从后台线程调用。您永远不应该尝试访问UI层上的任何内容(包括绑定的备份对象-在这里考虑WPF)

下面是一个用于消息框的示例

我想复制10个文件,然后在后台开始复制过程。出现错误(文件存在等),您希望提示用户覆盖-您可以显示一个消息框,请求用户确认

private void button1_Click(object sender, EventArgs e)
{
    BackgroundWorker bw = new BackgroundWorker();
    bw.RunWorkerCompleted += BwOnRunWorkerCompleted;
    bw.DoWork += BwOnDoWork;
    bw.RunWorkerAsync();
}

private void BwOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
    MessageBox.Show("This is a message from a background thread");
}

private void BwOnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs runWorkerCompletedEventArgs)
{
    MessageBox.Show("Your done");
}

我想可能会引发一些异常,但您的消息框不会显示,因为您是从后台线程而不是主UI线程调用的。您可能应该在UI线程上调用这些方法。我希望您有一个异常,消息框不会显示,因为它不是UI线程。请尝试记录异常,一般情况下,不要使用所有异常。这让调试成为一场噩梦,你现在可能已经意识到了这一点。你有没有见过catch块中的MessageBox?尝试在后台线程中抛出硬编码异常,以查看messagebox是否显示。我猜您的进程正在抛出错误。我猜我没有正确理解如何调用RunWorkerCompleted,因为在调用DoWork时,修订代码中的错误或确认消息框都不会显示。BackgroundWorker类的MSDN示例使我相信,一旦完成了DoWork,就会自动调用RunWorkerCompleted。如果没有实际未完成的代码的详细信息,读者将陷入黑暗。感谢您的回复。我从DoWork中删除了消息框,并添加了RunWorkerCompleted事件,但未显示RunWorkerCompleted中的确认框和错误消息框。从链接到的MSDN参考表中的第一个示例代码中,我认为在完成DoWork时会自动调用RunWorkerCompleted,这是错误的吗?@matt.f.c您确定正在连接事件处理程序吗?bw.RunWorkerCompleted+=BwOnRunWorkerCompleted;