Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a background worker in ASP.NET with AJAX

I have the need to perform a background task that has a progress bar that shows percentage done and a cancel button. Task specifics aside, for now, I just want to get an example working, so I just have the three main event handlers (DoWork, ProgressChanged, and RunWorkerCompleted) and a loop that just increments a counter and sleeps for 50ms in DoWork. However, it doesn't update except for once at the end.

In Windows Forms I use a Background worker and it functions correctly without any issues. I'd like to just use this same code. However, I have been seeing stuff that says ASP.NET must use AJAX to get the same functionality. So my questions are:

1) Do I really need AJAX to use the background worker?

2) If yes, I do need AJAX, what is the easiest, most simplest way a person that doesn't know a darn thing about AJAX could do to get the Background worker up and running on an ASP.NET webpage?

3) If no, I don't need AJAX, can anyone point me to a working sample that doesn't use it? I am interested even if it uses some other threading method than background workers.

Sorry for the multi-part question! If you can answer one or the other, it would be much appreciated. I don't really mind which method I end up using as long as it works.

Code for reference from the .cs page:

 protected void bwProcess_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
 { 
     lblProgress.Text = "Task Complete: " + e.Result;
 }

 protected void bwProcess_ProgressChanged(object sender, ProgressChangedEventArgs e)
 {
     lblProgress.Text = e.ProgressPercentage.ToString();
 }

 protected void bwProcess_DoWork(object sender, DoWorkEventArgs e)
 {
     for (int i = 0; i <= 100; i++)
     {
         if (bwProcess.CancellationPending)
         {
             lblProgress.Text = "Task Cancelled.";
             e.Cancel = true;
             return;
         }
         bwProcess.ReportProgress(i);
         Thread.Sleep(50);
     }
     e.Result = "100%";
}

protected void BWClick(object sender, EventArgs e)
{
    lblProgress.Text = "Firing Process...";
    bwProcess = new BackgroundWorker();
    bwProcess.WorkerReportsProgress = true;
    bwProcess.WorkerSupportsCancellation = true;
    bwProcess.DoWork += new DoWorkEventHandler(bwProcess_DoWork);
    bwProcess.ProgressChanged += new ProgressChangedEventHandler(bwProcess_ProgressChanged);
    bwProcess.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwProcess_RunWorkerCompleted);

    if (bwProcess != null)
    {
        bwProcess.RunWorkerAsync("StartAsynchronousProcess");
    }
}

Other notes: I have entered Async="True" and EnableSessionState="ReadOnly" into the @Page.

Thanks in advance!

like image 473
Brandi Avatar asked Oct 31 '12 19:10

Brandi


1 Answers

Web programming offer's many challenges which are easy to take for granted when desktop programming. Moving from one to the other can require a lot of changes. Spawning long-running threads is one of those things that require more care to avoid pitfalls. The application pool does not know about threads that you spawn so when it recycles it will kill those threads causing unexpected behavior in your application. See this post for more about that, Can I use threads to carry out long-running jobs on IIS?

This means you need to use a more persistent means to keep track of progress. A database would probably be best, but even a file would persist after the pool is recycled.


AJAX would be perfect for this because it will allow you to pull the progress from the database asynchronously in the background and update the webpage. Here is a breif example of how you might achieve this. All the percentage calculations are done on server side.

function getProgress() {
    $.ajax({
        url: '/progress',           // send HTTP-GET to /progress page
        dataType: 'json',           // return format will be JSON
        success: function(result) { // function to run once the result is pulled
            $("#p1").html('Percentage: %' + result);
            if (result == "100")
                clearInterval(window.progressID);
        }
    });
}

function startGetProgress() {
    window.progressID = setInterval(getProgress, 10000); // update progress every 10 seconds
}

The above example uses JQuery ajax method, http://api.jquery.com/jQuery.ajax/ so you will need to reference the JQuery library.

Whether you are using webforms or mvc you can add a web api controller to handle the ajax request. Let me know if you need me to clarify anything.

like image 58
Despertar Avatar answered Oct 30 '22 06:10

Despertar