如何处理BackgroundWorker线程中的异常?

时间:2010-02-20 16:05:19

标签: c# .net wpf multithreading backgroundworker

在WPF应用程序中,我有一个有计算机的数据库访问任务,定期由计时器运行,此任务已在BackgroundWorker线程中执行。

当连接尝试失败时,我通过try_catch构造引发异常,我想更新UI线程中的状态栏文本。

BackgroundWorker中是否有一些prebuild事件构建用于实现此功能,例如DoWorkEventHandlerRunWorkerCompletedEventHandler,可用于此目的吗?如果没有,怎么做得更好?

已编辑(已添加):

如果我想使用RunWorkerCompletedEventHandler参数处理e.Error内的异常,则它不起作用。如果我在BackgroundWorker线程中未处理异常,应用程序挂起并且调试器指向在BackgroundWorker线程内部执行的代码字符串,说: 异常未被处理用户代码

因此,在这种情况下,线程不会停止,向RunWorkerCompletedEventHandler发信号通知它因错误而停止,但整个应用程序停止工作。

5 个答案:

答案 0 :(得分:6)

RunWorkerCompletedEventArgs e的{​​{1}}包含属性RunWorkerCompletedEventHandler,它的类型为Exception。如果在后台线程的工作期间没有发生异常,则prpery为null。否则它包含发生的错误。

答案 1 :(得分:5)

可以使用Dispatcher.BeginInvoke从后台线程更新WPF UI。

例如,如果您的后台代码是Window的一部分,那么您可以更新TextBlock:

this.Dispatcher.BeginInvoke((Action)(() =>
    {
        textBlock.Text = "Connection Failed!";
    }));

编辑:

如果您的后台代码位于Window以外的类中,您可以创建一个界面来提供帮助:

public interface IShowStatus
{
    void ShowStatus(string message);
}

在您的窗口中实现界面

public void ShowStatus(string message)
{
   this.Dispatcher.BeginInvoke((Action)(() =>
       {
           textBlock.Text = message;
       }));
}

在你的班级中,后台工作人员创建一个属性来保存对接口的引用。

public IShowStatus StatusDisplay { get; set; }

在Window类中初始化背景类。

public void InitBackground()
{
    BackgroundClass background = new BackgroundClass();
    background.StatusDisplay = this;
    ...

最后在你的后台主题中你可以说:

StatusDisplay.ShowStatus("Connection Failed!");

答案 2 :(得分:3)

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
     Exception exceptionThrowDuringDoWorkEventHandler = e.Error;
}

答案 3 :(得分:3)

将后台工作程序的 WorkerReportsProgress 属性设置为 true ,然后为事件 ProgressChanged 添加事件处理程序。在下面的代码中,我还为Form.Load添加了一个事件处理程序。

现在尝试以下代码:

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            MessageBox.Show(e.UserState.ToString());
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            try
            {
                //some code that throws an exception
                throw new NotImplementedException();
            }
            catch (Exception ex) 
            {
                backgroundWorker1.ReportProgress(0/*percent of progress*/, ex);

            }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            backgroundWorker1.RunWorkerAsync();
        }

答案 4 :(得分:0)

  

如果我想在里面处理异常   RunWorkerCompletedEventHandler,使用e.Error参数   不起作用。如果我把未处理的异常留在了   BackgroundWorker线程,应用程序挂起,调试器指向   在BackgroundWorker线程内部执行的代码字符串,   说: 用户代码无法处理异常

     

因此,在这种情况下,线程不会停止,发信号通知   RunWorkerCompletedEventHandler它因错误而停止,但是   整个申请停止工作。

我对此非常好奇。尝试在控制台应用中运行以下代码,看看您的程序是否崩溃,或者错误是否显示在RunWorkerCompletedEventArgs中。

    static void Main(string[] args)
    {
        var bw = new BackgroundWorker();
        bw.DoWork += Bw_DoWork;
        bw.RunWorkerCompleted += Bw_RunWorkerCompleted;
        bw.RunWorkerAsync();

        Console.ReadKey();
    }

    private static void Bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Console.WriteLine("Complete.");
        Console.WriteLine(e.Error);
    }

    private static void Bw_DoWork(object sender, DoWorkEventArgs e)
    {
        throw new NotImplementedException();
    }