MoreThanChaos
MoreThanChaos

Reputation: 2092

BackgroundWorker stopped to pass exception to RunWorkerCompleted

I have very strange problem, back in a day I've started to develop application that do some product syncing. Download of product list had to be asynchronous to not lock GUI during updates. I did selected to do that task a background worker, all worked as it should, in case of errors I've handled them in RunWorkerCompleted.

Recently I was asked to do some improvements but now I do encounter a big problem, exceptions from inside DoWork method of one of background workers are thrown from within this method and not from RunWorkerCompleted.

Maybe some NET framework update changed backgroundWorker behavior that I don't know about? I really do not keep track of framework version, till now all worked fine. If it is significant I use SharpDevelop 5.1 as IDE.

I've been through several web searches about problem and any of solutions seems to not solve my problem or maybe i do apply it wrong way? so there are things I've tried

I don't know what changed, and have no clue how to fix it, does anyone has any suggestions as for how to solve my problem and make BackgroundWorker to pass error the way it should.

here is code that caused problem

    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
    }

Upvotes: 0

Views: 717

Answers (2)

MoreThanChaos
MoreThanChaos

Reputation: 2092

Apparently I haven't been concentrated and made mistake during testing relevance of e.Result.ToString() inside of RunWorkerCompleted and more precisely in error handling condition of RunWorkerCompleted. That does not change fact that from 2014 when i started my project things worked flawlessly with this exact code. Removing e.Result.ToString() from code fixes problem. It still remains mystery to me why it happens this way and why RunWorkerCompleted code causes throwing exception by DoWork

Upvotes: 0

Mick
Mick

Reputation: 6864

I ran your code, I'd suggest the BackgroundWorker is working as expected.

There are issues with your bgwProductListUpdaterRunWorkerCompleted you can expect it to throw a TargetInvocationException when an exception is thrown within bgwProductListUpdaterDoWork.

As documented here you can expect a TargetInvocationException accessing Result when Error != null and InvalidOperationException accessing Result when Cancelled is true. You should be checking both before accessing the Result property inside bgwProductListUpdaterRunWorkerCompleted.

When handling errors your should be extra careful as exceptions thrown during the handling of an exception can cause a lot of confusion.

Upvotes: 2

Related Questions