none
Background Worker not firing RunWorkerCompleted event? Could be related to cross domain web service execution?

    Question

  • Hey all,

    I have a background worker object that doesn't seem to be firing its RunWorkerCompleted event.  The event handlers are properly wired up during the intialization of the class:

    backgroundWorker.WorkerReportsProgress = true;
    backgroundWorker.ProgressChanged += OnBackgroundWorkerProgressChanged;
    backgroundWorker.RunWorkerCompleted += OnBackgroundWorkerRunWorkerCompleted;

    backgroundWorker.DoWork += BackgroundWorkFunction;
    backgroundWorker.RunWorkerAsync();

    In the debugger, I can step through the BackgroundWorkFunction and watch the function correctly execute and return.  I have a breakpoint in my OnBackgroundWorkerRunWorkerCompleted event handler, but it never gets hit after the BackgroundWorkFunction returns.

    There are some important details to know.  I have other tools which work just fine using this same code.  What is different about this particular project is that this code is being executed remotely by an IIS web service.  The code is executed by a local [TestMethod] in one domain, which calls a web service hosted on a different domain, which then executes this code for me.

    I've made simple toy applications which use a web service to create a background worker and it seems to work fine (although I wasn't testing cross domain, just with localhost).  I've tried completely rebuilding the project (new solution, new web service) to see if something just got screwed up in Visual C#, but I'm hitting hte same problem still. 

    I can't find any similar issues searching the internet, so I'm pretty stumped at what could be wrong, or even how to begin debugging :(.

    Any help is greatly appreciated.  Thanks! :)

    Friday, February 06, 2009 4:55 PM

Answers

  • Thanks for the tip JoGo.  I'll have to keep that in mind for future coding.  Sadly, the backgroundworker is in the API that I'm using, so it's not code I can easily change.

    I finally found a solution for this though.  The API that I'm using has windows forms code in it and as a result my project needs a reference to the windows forms libraries.

    I added the following line to my code before I invoke the portion of the API which creates the background worker:

    System.Windows.Forms.Application.DoEvents();

    and now the events seem to be getting generated/handled correctly.  I'm not sure of the in depth details on what this line changes exactly, but I'm assuming that if I created a new windows forms project, this line might appear somewhere in the autogenerated code.  Since this isn't a windows forms application though, I guess I needed to add it myself. 

    Perhaps someone can add a better explanation, but for now, in case anyone else hits this problem, here is the solution :).
    • Marked as answer by Fireborn Wednesday, March 18, 2009 3:58 PM
    Wednesday, March 18, 2009 3:58 PM

All replies

  • Out of curiosity, is your ProgressChanged handler getting called?
    http://blog.voidnish.com
    Friday, February 06, 2009 4:58 PM
  • How odd!

    This particular BackgroundWorkFunction doesn't call UpdateProgress (later uses of this object do, however).  I added an arbitrary UpdateProgress call to the BackgroundWorkFunction that it is currently failing on and re-ran the app to see if it would hit the ProgressChanged handler.

    To my surprise, it did.  To my greater surprise, it then hit the work completed event handler for the first time in weeks.  I'm not sure what happened, but somehow that change seems to have kicked the app in its head and got things working properly.  I'm going to play around with it a bit.  I'll try removing that UpdateProgress call and see if it reverts to its old behavior, or what.

    I'll post up if I figure out what may have happened.

    Friday, February 06, 2009 6:26 PM
  • Well, the update is frustraing, to say the least.

    The code was executing perfectly, but then failed due to a server-side timeout.  I corrected the timeout and then tried removing the the UpdateProgress call I had inserted in the BackgroundWorkFunction. 

    The behavior reverted.  The OnBackgroundWorkerRunWorkerCompleted event handler is never hit and the program hangs.  I tried putting the UpdateProgress call BACK to see if I could get it to start hitting the event handlers again, but now it doesn't hit either the ProgressChanged or RunWorkerCompleted event handlers.

    The intermittent behavior I've seen today has me stumped.  Could there be something about the web service that is causing all the events to lose their wiring?  I've checked to make sure fresh dll's are getting deployed every time I change the code and run, so it doesn't seem to be an issue of something not getting updated.
    Friday, February 06, 2009 8:58 PM
  • You need to add some error catching code to your DoWork event.  Any error will cause the symptoms you describe.
    Friday, February 06, 2009 10:55 PM
  • I've stepped through the DoWork handler with a remote debugger and watched it complete and return successfully.  Could the problem you are describing be a result of a lower level error which is handled by lower level code and never reported to me?

    I'm imaging a case where there is a low level error which we ignore at some point deeper in the code which doesn't affect normal execution, but causes problems when executed by the web service.  Is that what you're thinking might be the problem?

    Friday, February 06, 2009 11:18 PM
  • Masking errors will do it.  If you have any empty Catch blocks, get rid of them.
    Friday, February 06, 2009 11:29 PM
  • Sounds like a probable candidate.  I'll start digging and let you guys know.  Thanks a ton!
    Friday, February 06, 2009 11:32 PM
  • I found a purposeful ArgumentException that the code throws, and then just catches and continues.  Was hoping to find something more low level.  I'll look a bit more in depth and see if I can't find anything else.  If not, I'll modify the library to not throw that ArgumentException and see if it makes a difference.
    Tuesday, February 10, 2009 12:59 AM
  • Alright.  I've run through a few times, and can't find any lower level exceptions that are being masked.  In the exception settings for the debugger I have it set to break on all exceptions, or at least, all exceptions in the default list:

    C++ Exceptions
    CLR Exceptions
    Managed Debugging Assistants
    Native Run-Time Checks
    Win32 Exceptions

    Perhaps there are more I can add to this list and monitor?

    I removed the argument exception that the code was generating and have run through the whole routine several times without any detected errors and still seem to be losing my event handler wiring.

    Is there a way in the debugger to monitor who is subscribed to an event so I can try to find at what point I'm losing my wiring?
    Tuesday, February 10, 2009 6:56 PM
  • Post  the code containing the RunWorkerAsync statement.  (Just a hunch)
    Tuesday, February 10, 2009 7:19 PM
  • I basically call a function RunBackgroundWorker(BackgroundWorkFunction) which appears below:

    private void ExecuteBackgroundWorker(DoWorkEventHandler doWorkHandler)  
    {  
        _backgroundWorker.DoWork += doWorkHandler;  
        _backgroundWorker.RunWorkerAsync();  

    _backgroundWorker is a member for the class:

    private readonly BackgroundWorker _backgroundWorker = new BackgroundWorker();  
     

    The variable is then initialized in the constructor:

    public Class(/* unrelated arguments */)  
    {  
        //  
        // Initialize BackgroundWorker.  
        //  
        _backgroundWorker.WorkerReportsProgress = true;  
        _backgroundWorker.ProgressChanged += OnBackgroundWorkerProgressChanged;  
        _backgroundWorker.RunWorkerCompleted += OnBackgroundWorkerRunWorkerCompleted;  
    Tuesday, February 10, 2009 8:20 PM
  • Well, you're definitely on track for the location of the issue.  I'm doing some ghetto printf style debugging using the ReportProgress function and the ProgressChanged event handler.  My modified RunBackgroundWorker function from the last post:

    private void RunBackgroundWorker(DoWorkEventHandler doWorkHandler)  
    {  
        //  
        // Test  
        //  
        _backgroundWorker.ReportProgress(4);  
     
        _backgroundWorker.DoWork += doWorkHandler;  
     
        //  
        // Test  
        //  
        _backgroundWorker.ReportProgress(4);  
     
        _backgroundWorker.RunWorkerAsync();  
     
        //  
        // Test  
        //  
        _backgroundWorker.ReportProgress(4);  

    I hit the breakpoint in the ProgressChanged event for the first two ReportProgress calls, but not the last.  Basically, any ReportProgress call stops hitting the ProgressChanged event handler after the RunWorkerAsync() is called.

    I'm going to look into why that might be.  Anyone have any ideas/tips?
    Tuesday, February 10, 2009 8:57 PM
  • I don't understand the code you posted.  Post the code that calls that code.
    Tuesday, February 10, 2009 9:01 PM
  • ///  
    /// This is the web service function that I am remotely  
    /// calling.  
    ///   
    public bool RemoteDataValidate()  
    {  
        /// Some configuration stuff excluded  
          
        dataValidator = new DataValidator(databaseConnection);  
     
        dataValidator.ValidateAsync();  
     
        eventWaitHandle.Wait(-1);  
     
        /// Check to see if validation succeeded and return result  

    ///  
    /// The ValidateAsync function inside my dataValidator function  
    ///  
    public void ValidateAsync()  
    {  
        /// Some Logging stuff excluded  
     
        RunBackgroundWorker(Validate);  
    Tuesday, February 10, 2009 9:31 PM
  • There it is:  eventWaitHandle.Wait(-1);

    You have to let that funcition complete.  Remove that statement.  If you want to wait, use a timer.
    Tuesday, February 10, 2009 11:18 PM
  • Sorry, I probably should have clarified that I am signaling my eventWaitHandle in my OnBackgroundWorkerRunWorkerCompleted function.  The problem is that the event handler never gets executed, so I never signal and allow my web service call to complete.

    I'm still trying to figure out why my event handlers seem to not get executed once I make the call to RunWorkerAsync().

    Tuesday, February 10, 2009 11:56 PM
  • Still working on the issue.  I'll post when I find the solution. 

    I've managed to extract the web service from the equation and can reproduce the problem when running the code locally.  I wonder if it has anything to do with running the code through the visual studio test framework.  I'll be playing around with that next.
    Monday, February 23, 2009 5:38 PM
  • one thing to be very careful of:  the main purpose of the background worker control is to ensure that (RunWorkerCompleted, ReportProgress &c) notifications are getting called on a main application thread, or GUI thread.  If you are invoking a background worker control from a non-gui thread, then you are much more likely to run into problems.  So, I would say, use backgroundworker only in windows forms programming and then only from the gui thread.  In all other scenarios do your own threading.
    Thursday, March 12, 2009 2:32 AM
  • Thanks for the tip JoGo.  I'll have to keep that in mind for future coding.  Sadly, the backgroundworker is in the API that I'm using, so it's not code I can easily change.

    I finally found a solution for this though.  The API that I'm using has windows forms code in it and as a result my project needs a reference to the windows forms libraries.

    I added the following line to my code before I invoke the portion of the API which creates the background worker:

    System.Windows.Forms.Application.DoEvents();

    and now the events seem to be getting generated/handled correctly.  I'm not sure of the in depth details on what this line changes exactly, but I'm assuming that if I created a new windows forms project, this line might appear somewhere in the autogenerated code.  Since this isn't a windows forms application though, I guess I needed to add it myself. 

    Perhaps someone can add a better explanation, but for now, in case anyone else hits this problem, here is the solution :).
    • Marked as answer by Fireborn Wednesday, March 18, 2009 3:58 PM
    Wednesday, March 18, 2009 3:58 PM
  • I had the same problem and found the solution to be setting a result value:

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    {
     ...
     e.Result = <any non-null value>;
    }

    If you do set e.Result, OnBackgroundWorkerRunWorkerCompleted is called.

    If you don't care abut the return value, just set e.Result = true.

    If you don't set e.Result, OnBackgroundWorkerRunWorkerCompleted is not called.
    • Proposed as answer by dolan.dave Friday, July 06, 2012 8:10 PM
    Wednesday, November 03, 2010 1:38 AM
  • I have encountered similar problem and your solution has done it for me. Thanks for sharing.

    I was converting a WinForms application into a windows service while making minimal changes to the original Winforms class. So all I do is instanciate the winforms class in the service and execute some method. Because the object is no longer running as a GUI application the background working was doing the work but not firing events. Calling System.Windows.Forms.Application.DoEvents(); got events firing.

    IT and Communications Jobs

    Friday, November 23, 2012 12:33 PM
  • Old post, but this is still top result on Google.  After scratching my head for a day and a million Debug.writelines later, calling this line right before I initialized my BackgroundWorker made my code start to behave.

    System.Windows.Forms.Application.DoEvents();

    Thank you, OP.

    Thursday, March 27, 2014 11:21 AM