-2

这个让我难住了。我有一个简单的实用程序来帮助企业安装软件。一个组件备份用户当前在其机器上拥有的 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)
{
    ...
}

这有效,但不会产生预期的结果。我将此操作放在后台线程上,因为每个用户备份的总文件大小可能接近一两个 GB。每次运行时,目标中的一些(但不是全部)文件和文件夹都会复制到目标,并且复制的文件夹每次都不同。有时只复制少数文件和文件夹,有时几乎所有内容都被复制,但绝不是整个目标。如果这个操作放在一个简单的控制台应用程序中,它每次都有效。关于导致它无法完成 DoWork 方法中的所有工作的 BackgroundWorker 类,我有什么需要了解的吗?

编辑:

我想我可能过于复杂了 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 没有成功,并且永远无法弄清楚为什么只复制了一些文件。感谢大家的帮助!

4

2 回答 2

4

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

请记住,在另一个非 UI 线程上BackgroundWorker执行您的方法,因此在此处调用不是一个好主意。如果你在 UI(“前台”)线程上运行,你应该只做 UI 的东西:DoWorkMessageBox.Show

您必须小心不要在 DoWork 事件处理程序中操作任何用户界面对象。相反,通过 ProgressChanged 和 RunWorkerCompleted 事件与用户界面进行通信。 —该课程的 MSDN 参考页面BackgroundWorker

我可以想象,如果您的方法中某处发生异常,并且您想在块中显示一个消息框,则catch此调用会触发另一个异常,该异常没有得到处理......因此您的方法过早中止。

于 2012-05-20T18:03:24.943 回答
1

这是一个示例,显示您可以从后台线程调用消息框。MessageBox.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");
}
于 2012-05-20T19:25:18.280 回答