Background Processes in ASP.NET Web Forms

Sometimes you need to run operations behind the scenes, in a different thread from the one that ASP.NET Framework uses to process Web Pages. Multitasking in Web Pages can be quite tricky and difficult cause meshing with threads can make your pages not responding. Several tutorials exist out on internet about supporting background processes in .NET, but most of them are applied in Windows Forms. If you try to run the same code in ASP.NET Web Forms Application you will probably be disappointed by the fact that pages don’t work pretty well (they usually hang). This post will show you how to use a BackgroundWorker class in order to run background processes in ASP.NET Web Forms. The idea is this: We are going to create a UI and let the user to add Person objects to a list of Person. The Person class will be the following:

public class Person
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public string Address { get; set; }
    }

Though, user will not provide value for the Id but instead, we ‘ll let the background process do it for him. We will add a button to display current state of the list in order to check Person’s ID values. Two buttons also are going to be added. The first one will be the STOP button which is going to put the process in IDLE mode (in other words thread is going to sleep) and the START button which is going to restart the process. What we are going to see is that as long as the Background Process is running, all Id property values will have valid/updated values but as long as it’s in IDLE mode, all Person objects that haven’t be processed by the BackgroundWorker object, will have the default value 0. Mind that when I said valid values, I meant that the first Person object must have Id=0, the second Id=1 and so on.
backworker_00
Take a look at the following GIF image and notice that Id values are automatically increased by one by the background process running in Application level.
backworkgif
In VS 2012 add a new ASP.NET Empty Web Application project named AspNetBackgroundProcess. Right click your project and add an Application Configuration file leaving the default name “Global.asax”. You will use this file to create and configure our BackgroundWorker object since it make sense to keep the background process in application level and not in a simple page level. Change Global.asax file contents to the following:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;

namespace AspNetBackgroundProcess
{
    public class Global : System.Web.HttpApplication
    {
        public static BackgroundWorker worker = new BackgroundWorker();
        public static int ID = 0;
        public static List<Person> personList = new List<Person>();
        public static bool stopWorker = false;

        protected void Application_Start(object sender, EventArgs e)
        {
            worker.DoWork += new DoWorkEventHandler(DoWork);
            worker.WorkerReportsProgress = true;
            worker.WorkerSupportsCancellation = true;
            worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(WorkerCompleted);
            // Calling the DoWork Method Asynchronously
            worker.RunWorkerAsync();
        }

        protected void Application_End(object sender, EventArgs e)
        {
            if (worker != null)
                worker.CancelAsync();
        }

        private static void DoWork(object sender, DoWorkEventArgs e)
        {
            foreach (Person p in personList)
            {
                p.Id = ID++;
            }
        }

        private static void WorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            ID = 0;
            BackgroundWorker worker = sender as BackgroundWorker;
            if (worker != null)
            {
                System.Threading.Thread.Sleep(3000);
                if (!stopWorker)
                {
                    worker.RunWorkerAsync();
                }
                else
                {
                    while (stopWorker)
                    {
                        Thread.Sleep(6000);
                    }
                    worker.RunWorkerAsync();
                }
            }
        }

    }
}

Here we have created a BackgroundWorker object named worker and we bind it’s worker.DoWork event to a DoWork function. This means that each time the worker runs, this function will run.

worker.DoWork += new DoWorkEventHandler(DoWork);

Also we defined that each time that operation is completed another function is going to run, where the worker object will decide whether to proceed to a new process cycle or to sleep depending on a stopWorker bool variable.

worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(WorkerCompleted);

The DoWork function simply put valid Id values for the Person objects exist currently in the personList. Now let’s create the User interface. Add a new Web Form page with a code behind file. Name the page Default.aspx and paste the following code.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="AspNetBackgroundProcess.Default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <style type="text/css">
        .auto-style1 {
            width: 330px;
            border: 1px solid royalblue;
        }
        .auto-style2 {
            font-weight:bold;
        }
        .auto-style3 {
            width: 381px;
        }
    </style>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    
        <asp:Label ID="lblAddPerson" runat="server" Text="Add a new Person:" Font-Bold="True" ForeColor="#6600FF"></asp:Label>
        <br />
        <table class="auto-style1">
            <tr>
                <td class="auto-style2">Name:</td>
                <td class="auto-style3">
                    <asp:TextBox ID="txtName" runat="server"></asp:TextBox>
                </td>
            </tr>
            <tr>
                <td class="auto-style2">Age:</td>
                <td class="auto-style3">
                    <asp:TextBox ID="txtAge" runat="server"></asp:TextBox>
                </td>
            </tr>
            <tr>
                <td class="auto-style2">Address:</td>
                <td class="auto-style3">
                    <asp:TextBox ID="txtAddress" runat="server"></asp:TextBox>
                </td>
            </tr>
            <tr>
                <td class="auto-style2" colspan="2">
                    <asp:Button ID="btnAddPerson" runat="server" Text="Add Person" Width="215px" OnClick="btnAddPerson_Click" BackColor="#6666FF" BorderColor="White" ForeColor="White" />
                </td>
            </tr>
        </table>
        <div style="background-color:royalblue;width: 310px;padding: 10px;color:cornsilk">
        <asp:Label ID="lblBackgroundProc" runat="server" Text="Background Process:"></asp:Label>
&nbsp;
        <asp:Button ID="btnStop" runat="server" Text="Stop" Width="75px" OnClick="btnStop_Click" />
&nbsp;
        <asp:Button ID="btnStart" runat="server" Text="Start" Width="75px" OnClick="btnStart_Click" Enabled="False" />
            </div>

        <asp:Button ID="btnUpdateList" runat="server" OnClick="btnUpdateList_Click" Text="Update List Data" Width="330px" />
        <br />
        <asp:GridView ID="gridPersonList" runat="server" CellPadding="4" ForeColor="#333333" GridLines="None" Width="330px">
            <AlternatingRowStyle BackColor="White" ForeColor="#284775" />
            <EditRowStyle BackColor="#999999" />
            <FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
            <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />
            <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" />
            <RowStyle BackColor="#F7F6F3" ForeColor="#333333" />
            <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />
            <SortedAscendingCellStyle BackColor="#E9E7E2" />
            <SortedAscendingHeaderStyle BackColor="#506C8C" />
            <SortedDescendingCellStyle BackColor="#FFFDF8" />
            <SortedDescendingHeaderStyle BackColor="#6F8DAE" />
        </asp:GridView>
    </div>
    </form>
</body>
</html>

Switch to the code behind file now and paste the following code:

namespace AspNetBackgroundProcess
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                btnStop.Enabled = !btnStart.Enabled;
            }
        }

        protected void btnAddPerson_Click(object sender, EventArgs e)
        {
            Global.personList.Add(new Person {
                Name = txtName.Text,
                Age = Int32.Parse(txtAge.Text),
                Address = txtAddress.Text
            });
        }

        protected void btnUpdateList_Click(object sender, EventArgs e)
        {
            gridPersonList.DataSource = Global.personList;
            gridPersonList.DataBind();
        }

        protected void btnStop_Click(object sender, EventArgs e)
        {
            Global.stopWorker = true;
            btnStop.Enabled = false;
            btnStart.Enabled = true;
        }

        protected void btnStart_Click(object sender, EventArgs e)
        {
            Global.stopWorker = false;
            btnStart.Enabled = false;
            btnStop.Enabled = true;
        }
    }
}

What we do here is very simple. The Add Person button will add a new Person object to the Global.personList while Stop and Start buttons change the Global.stopWorker value to true and false respectively. That’s the value the worker checks when it’s operation has completed and decides whether to restart or to sleep. Build and run your application.
backworker_01
Try to add 3-4 objects and click the Update button. Ensure that All Objects have been assigned with valid Ids.
backworker_02
Now press the Stop button to make the worker sleep while keep adding new Persons to the list. Press Update to see the result. Then press again the Start button and ensure the your worker was restarted.
backworker_03
This is pretty much a simple way to use background processes in ASP.NET Web Forms. For sure there are other alternatives such as using WCF services running and listening to events but sometimes a background worker can be quite useful. You can download the AspNetBackgroundProcess project we created from here. i hope you enjoyed the post.

Advertisements


Categories: ASP.NET

Tags: , ,

3 replies

  1. WHY SHOULD I START AND STOP THE BACKGROUND WORKER?
    I NEED IT TO RUN AS THE CODE IS RUNNING AND STOP AUTOMATICALLY WHEN THE RESULT IS OUT

Trackbacks

  1. Sending Emails in ASP.NET: Do it right « chsakell's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Diary Of A Programmer

Because every day is worth noting

Chara Plessa

The purpose of this blog is to broaden my education, promote experimentation and enhance my professional development. Albert Einstein once said that “If you can’t explain it simply, you don’t understand it well enough” and I strongly believe him!

chsakell's Blog

Anything around ASP.NET MVC,WEB API, WCF, Entity Framework & AngularJS

Kumikoro

A Front End Developer's Blog

Muhammad Hassan

Full Stack Developer | ASP.NET | MVC | WebAPI | Advanced Javascript | AngularJS | Angular2 | C# | ES6 | SQL | TypeScript | HTML5 | NodeJS, MS candidate @LUMS, Grad & EX-Adjunct Faculty @NUCES-FAST, seasonal blogger & open-source contributor. Seattle, WA.

Software Engineering

Web development

IEvangelist

.NET, ASP.NET, C#, MVC, TypeScript, AngularJS

leastprivilege.com

Dominick Baier on Identity & Access Control

Happy DotNetting

In Love with Technology

Knoldus

Knols of experience to your advantage

knowshnet

Search - Read - Request - Share

Rahul's space

Learn, Share and Grow with me !

Dhananjay Kumar

Developer Evangelist @Infragistics | MVP @Microsoft |

SQL Authority with Pinal Dave

SQL Server Performance Tuning Expert

Conficient Blog

Random bits of tech from @conficient

Code! Code! Code!

SOLID & KISS

Code Wala

Designing and coding

Microsoft Mentalist

A way to start with Microsoft Technologies

Tony Sneed's Blog

A glimpse into the lives of Tony & Zuzana Sneed

%d bloggers like this: