【问题标题】:How to handle exceptions from a BackgroundWorker thread?如何处理来自 BackgroundWorker 线程的异常?
【发布时间】:2010-02-20 16:05:19
【问题描述】:

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

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

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

已编辑(添加):

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

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

【问题讨论】:

  • 感谢大家的回答!考虑到一些答案,我用更多细节更新了我的问题。

标签: c# .net wpf multithreading backgroundworker


【解决方案1】:

RunWorkerCompletedEventHandlerRunWorkerCompletedEventArgs e 包含属性Error,它属于异常类型。如果在后台线程工作期间没有发生异常,则该 prpery 的值为 null。否则它包含发生的错误。

【讨论】:

    【解决方案2】:

    可以使用 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!");
    

    【讨论】:

    • 在我的情况下,后台代码不是 Window 的一部分,但它在单独的类中运行。此外,异常发生在静态方法中。因此,在这种情况下,THIS 关键字无效。请帮助我理解,在这种情况下如何引用我的主 UI 窗口?
    • 我在回复您的问题时添加了注释。
    【解决方案3】:
    private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
         Exception exceptionThrowDuringDoWorkEventHandler = e.Error;
    }
    

    【讨论】:

    • 当我尝试从 BackgroundWorker 线程抛出异常时,应用程序会崩溃:用户代码未处理异常。我从来没有到达 bw_RunWorkerCompleted。我错过了什么吗?
    【解决方案4】:

    将后台worker的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();
            }
    

    【讨论】:

      【解决方案5】:

      如果我想处理里面的异常 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();
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-07
        • 2012-05-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-05
        相关资源
        最近更新 更多