locked
Can a BackgroundWorker call RunWorkerCompleted events from an ASP.NET Web application? RRS feed

  • Question

  • User314655009 posted

    Hello,

    My RunWorkerCompleted event handler is not called for a BackgroundWorker in an ASP.NET Web application.

    The BackgroundWorker is created during an asynchronous postback of a button.

    I also continue to call the postback event recursively in order to maintain a reverse ajax session.

    Here is my code:  (Although this is a dll, I tried the same code in the web page.  With the same result.)

    {
        public class Wait
        {
            public int NumberOfSeconds { get; private set; }
    
            public Wait()
            {
                NumberOfSeconds = DEFAULT_NUMBER_OF_SECONDS;
            }
    
            public Wait(int iNumberOfSeconds)
            {
                NumberOfSeconds = iNumberOfSeconds;
            }
    
            public void StartWait()
            {
                backgroundWorker1 = new BackgroundWorker();
                backgroundWorker1.WorkerSupportsCancellation = true;
                backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork);
                backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted);
                backgroundWorker1.RunWorkerAsync();
            }
    
            public void StopWait()
            {
                if (backgroundWorker1.WorkerSupportsCancellation == true)
                {
                    // Cancel the asynchronous operation.
                    backgroundWorker1.CancelAsync();
                }
            }
    
            private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
            {
                Thread.Sleep(NumberOfSeconds * 1000); //in milliseconds
                throw new Exception("DialogWait: timer has elapsed."); //this causes program termination from an uncaught exception
            }
            
    //this method is never called
            private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                if (e.Cancelled == false)
                {
                    throw new Exception("DialogWait: timer has elapsed.");
                }
            }
    
            /// <summary>
            /// background worker
            /// </summary>
            private BackgroundWorker backgroundWorker1 = new BackgroundWorker();
    
            /// <summary>
            /// default timeout (in seconds)
            /// </summary>
            private const int DEFAULT_NUMBER_OF_SECONDS = 30; 
        }
    }
    

    The exception in the DoWork method terminates the program due to an uncaught exception.  The RunWorkCompleted event handler is never called.  (Even without the exception thrown.)

    Any suggestions?

    Thursday, January 14, 2016 8:09 PM

Answers

  • User753101303 posted

    The BackgroundWorker is for Windows Forms and it would be likely hard to use that for ASP.NET which doesn"t follow at all the same execution model (in particular you have server side code running only when an http request is in progress).

    As I said earlier my understanding is that what you call "reverse Ajax" could be done using SignalR (which allows server side code to send data to the client). But it seems you don"t even need that. If it really happens based on a timer, you could just have a client side timer that would then fetch the next string from the server. No need to have some server side code running if the purpose is just to wait. At least it would my approach given my understanding about what you are actually trying to do.

    Edit: I'm thinking about http://www.w3schools.com/jsref/met_win_settimeout.asp

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, January 19, 2016 9:29 PM

All replies

  • User753101303 posted

    Hi,

    BackgroundWorker is an (old) Windows form approach for background processing.

    I also continue to call the postback event recursively in order to maintain a reverse ajax session.

    Humm. Not sure to get what you mean.  Keep in mind that even if you "recursively" do a postback, each http request is still processed separately by the web server and no state is maintained between one request and the next http request.

    For now my understanding would be that you are trying to send back some information from the server to your page while some server side processing is taking place.  So it seems yo me you might be looking for something such as http://www.asp.net/signalr

    Else try first to explain your final goal.

    Thursday, January 14, 2016 9:58 PM
  • User314655009 posted

    Hello,

    Instead of returning from the asyncpostback, I call the event handler with null parameters, check for the null parameter, and sleep for one second with subsequent calls to the event handler.  This maintains the reverse ajax connection and this still provides page responsiveness.

    Here is my code:

            protected void EnterButton_Click(object sender, EventArgs e)
            {
                try
                {
                    if (sender == null && e == null)
                    {
                        Thread.Sleep(1000);
                    }
                    else
                    {
    //event handler code here
                    }
                    EnterButton_Click(null, null);
                }
                catch (TimeoutException toe)
                {
                    //say "Are you there?" etc.
    
                }
                catch (Exception ex)
                {
    
    
                }
    }

    What do you recommend over BackgroundWorker?

    Thanks.

    Friday, January 15, 2016 12:12 PM
  • User753101303 posted

    At some point you'll have a "stack overflow" error.

    For now my understanding, is that you are trying to show some progress to the user while a server side processing is going on. I would then use http://www.asp.net/signalr (as suggested earlier). It allows to call *immediately* into a client side JavaScript function while your server side code is still running. So for example you can process a file and send back to the client side that you are at page x out of y and show that immediately before processing the next page etc...

    Else rather than showing some code, tell first your goal ie things like :
    - "I want to report progress to users while a server side processing is taking place"
    - or "I want to run a task each minutes (or second really !) even if none is connected" etc...

    In short to suggest something we have first to understand what is the final goal.

    Friday, January 15, 2016 1:16 PM
  • User314655009 posted

    Hello,

    What do you recommend as an alternative to BackgroundWorker?

    I did have some problems on catching an exception from a normal Thread.

    Thanks.

     

    Friday, January 15, 2016 3:15 PM
  • User753101303 posted

    Once again the point is that I'm seeing some code without knowing exactly what you are trying to do.

    So once again for now my understanding is that while a postback is in progress (and that may take 5 minutes or whatever) you are trying to find a mechanism to show the user at which step this process is currently. So first, could you confirm this is what you are trying to do?

    If confirmed, I would use SignalR to do so (see for example https://www.safaribooksonline.com/blog/2014/02/06/server-side-signalr/). It allows to immediately send data client side while the postback is still in progress.

    If this is not what you are trying to do, PLEASE do explain what you are trying to do (a background worker is for reporting progress to the UI on the same machine so my guess is that you are trying to report progress but for a web app, the processing and the UI are not on the same machine and the architecture is entirely different).

    Friday, January 15, 2016 3:31 PM
  • User314655009 posted

    Hello,

    I want to use reverse ajax and maintain an open connection.  When a timeout occurs, hopefully from a BackgroundWorker, a "wake up" text will be displayed.  Like, "Are you there?" or "I am waiting."

    My issue is that the completed event handler is not called. nor can I throw an exception from the DoWork handler.

    That's it.

    Thanks.

    Tuesday, January 19, 2016 8:35 PM
  • User753101303 posted

    The BackgroundWorker is for Windows Forms and it would be likely hard to use that for ASP.NET which doesn"t follow at all the same execution model (in particular you have server side code running only when an http request is in progress).

    As I said earlier my understanding is that what you call "reverse Ajax" could be done using SignalR (which allows server side code to send data to the client). But it seems you don"t even need that. If it really happens based on a timer, you could just have a client side timer that would then fetch the next string from the server. No need to have some server side code running if the purpose is just to wait. At least it would my approach given my understanding about what you are actually trying to do.

    Edit: I'm thinking about http://www.w3schools.com/jsref/met_win_settimeout.asp

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, January 19, 2016 9:29 PM