BackgroundWorker停止将异常传递给RunWorkerCompleted

时间:2016-12-07 02:13:32

标签: c# .net exception backgroundworker

我有一个非常奇怪的问题,在一天之内我开始开发一些产品同步的应用程序。下载产品列表必须是异步的,以便在更新期间不锁定GUI。我确实选择了后台工作人员执行该任务,所有工作都应该正常工作,如果出现错误,我已经在 RunWorkerCompleted 中处理了它们。

最近我被要求做一些改进,但现在我确实遇到了一个大问题,其中一个后台工作者的 DoWork 方法的异常是从这个方法中抛出而不是来自 RunWorkerCompleted

也许某些.NET框架更新改变了我不了解的 backgroundWorker 行为?我真的没有跟踪框架版本,直到现在一切正常。如果它很重要,我使用SharpDevelop 5.1作为IDE。

我经历了几次关于问题的网络搜索,而且任何解决方案似乎都无法解决我的问题,或者我可能错误地应用它?所以我尝试过的东西

  • 在非调试模式下运行应用程序 - 没有任何更改
  • DoWork 中捕获例外并取消后台工作人员 - 然后工作人员已完成但没有错误传递给 RunWorkerCompleted
  • RunWorkerCompleted 内部删除 e.Result.ToString(),因为它必须打破一些东西 - 对我来说,这开始工作并没有错,删除它或它保持原样没有区别

我不知道发生了什么变化,并且不知道如何解决它,是否有人对如何解决我的问题有任何建议,并使 BackgroundWorker 以错误的方式传递错误。

这是导致问题的代码

    public string WEB_JSON_RAW_DATA  {get;set;} 

    bgwProductListUpdater = new BackgroundWorker();
    bgwProductListUpdater.WorkerReportsProgress = true;
    bgwProductListUpdater.DoWork += new DoWorkEventHandler(this.bgwProductListUpdaterDoWork);
    bgwProductListUpdater.ProgressChanged += new ProgressChangedEventHandler(this.bgwProductListUpdaterProgressChanged);
    bgwProductListUpdater.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.bgwProductListUpdaterRunWorkerCompleted);

    void bgwProductListUpdaterDoWork(
        object sender, 
        System.ComponentModel.DoWorkEventArgs e)
    {       
        //source of exception
        WEB_JSON_RAW_DATA += (string)ApiClient.Get("/admin/product.json?GET_LIST");

        //rest of json processing
    }

    void bgwProductListUpdaterProgressChanged(
        object sender, 
        System.ComponentModel.ProgressChangedEventArgs e)
    {
        //this method is empty, it was intended to be used but then no need of progress repporting was needed
        //it was all the time in my code so i do paste it as well
    }

    void bgwProductListUpdaterRunWorkerCompleted(
        object sender, 
        System.ComponentModel.RunWorkerCompletedEventArgs e)
    {
        if(e.Error != null)
        {
            string ExtraErrorData = "";

            if (e.Error.Data.Count > 0) 
            {
                 foreach (DictionaryEntry de in e.Error.Data) 
                    ExtraErrorData += string.Format(
                        "    Key: {0,-20}      Value: {1}", 
                        "'" + de.Key.ToString() + "'", 
                        de.Value) + Environment.NewLine;
            }

            Common.LogWindow.Log(string.Format("{0} - Downloading product list - {1}",ShortName, 
                Environment.NewLine + e.Error.Message +
                Environment.NewLine + ExtraErrorData +
                Environment.NewLine + e.Result.ToString()));
                ShopHasErrors = true;
        }

        //do rest of finalizing
    }

2 个答案:

答案 0 :(得分:2)

我运行了你的代码,我建议BackgroundWorker按预期工作。

bgwProductListUpdaterRunWorkerCompleted存在问题,当bgwProductListUpdaterDoWork中抛出异常时,您可以预期它会抛出TargetInvocationException。

如记录here,您可以预期TargetInvocationException在Error!= null时访问Result,而InvalidOperationException在Canceled为true时访问Result。您应该在访问bgwProductListUpdaterRunWorkerCompleted中的Result属性之前检查两者。

在处理错误时,您应该格外小心,因为在处理异常期间抛出的异常会导致很多混淆。

答案 1 :(得分:0)

显然,在测试 RunWorkerCompleted <内的 e.Result.ToString() 的相关性时,我没有集中注意力并犯了错误/ em> ,更确切地说是 RunWorkerCompleted 的错误处理条件。这并没有改变这一事实,从2014年开始我的项目开始,这些确切的代码完美无缺。从代码中删除 e.Result.ToString() 修复了问题。我仍然不知道为什么它会以这种方式发生以及为什么 RunWorkerCompleted 代码导致抛出异常 DoWork