Home » C# ProgrammingRSS

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

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! :)

 

20 Answers Found

 

Answer 1

Out of curiosity, is your ProgressChanged handler getting called?
 

Answer 2

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.

 

Answer 3

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.
 

Answer 4

You need to add some error catching code to your DoWork event.  Any error will cause the symptoms you describe.
 

Answer 5

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?

 

Answer 6

Masking errors will do it.  If you have any empty Catch blocks, get rid of them.
 

Answer 7

Sounds like a probable candidate.  I'll start digging and let you guys know.  Thanks a ton!
 

Answer 8

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.
 

Answer 9

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?
 

Answer 10

Post  the code containing the RunWorkerAsync statement.  (Just a hunch)
 

Answer 11

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;  
 

Answer 12

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?
 

Answer 13

I don't understand the code you posted.  Post the code that calls that code.
 

Answer 14

///
/// This is the web service function that I am remotely
/// calling.
/// 
publicbool 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
///
publicvoid ValidateAsync()  
{  
/// Some Logging stuff excluded
    RunBackgroundWorker(Validate);  
 

Answer 15

There it is:  eventWaitHandle.Wait(-1);

You have to let that funcition complete.  Remove that statement.  If you want to wait, use a timer.
 

Answer 16

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().

 

Answer 17

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.
 

Answer 18

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.
 

Answer 19

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 :).
 

Answer 20

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.
 
 
 

<< Previous      Next >>


Microsoft   |   Windows   |   Visual Studio   |   Follow us on Twitter