C#BackgroundWorker_DoWork只做一些工作

时间:2012-05-20 17:58:38

标签: c# .net backgroundworker

这个让我难过。我有一个简单的实用程序,用于帮助企业安装软件。一个组件备份用户当前在其计算机上的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。每次运行时,目标中的一些(但不是全部)文件和文件夹都会复制到目标,并且每次复制的文件夹都会有所不同。有时只复制少量文件和文件夹,有时几乎所有内容都被复制,但从不复制整个目标。如果此操作放在一个简单的控制台应用程序中,它每次都有效。有什么我需要了解的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失败了,但却从未弄清楚为什么只复制了一些文件。谢谢大家的帮助!

2 个答案:

答案 0 :(得分:4)

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

请记住BackgroundWorker在另一个非UI线程上执行您的DoWork方法,因此在那里调用MessageBox.Show不是一个好主意。如果你在UI("前景")线程上运行,你应该只做UI内容:

  

您必须小心不要操作DoWork事件处理程序中的任何用户界面对象。而是通过ProgressChanged和RunWorkerCompleted事件与用户界面进行通信。     - MSDN reference page for the BackgroundWorker class

我可以想象,如果您的方法中某处出现异常,并且您想在catch块中显示一个消息框,则此调用会触发另一个异常,该异常无法处理。因此你的方法过早地中止了。

答案 1 :(得分: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");
}