65.9K
CodeProject is changing. Read more.
Home

QBWI - Your Background Process Rescuer

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.98/5 (91 votes)

Jul 29, 2016

CPOL
viewsIcon

18431

How to utilize QueueBackgroundWorkItem(QBWI) for web applications that run a background process in IIS environment.

Introduction

In web environment (specifically ASP.NET), sometimes there is a need to run a process in the background due to a continuation of current process or as an independent long running process. If the web application happens to be hosted in IIS, the background process may be interrupted by IIS due to recycling of an App Pool[^]. QueueBackgroundworkItem(QBWI)[^] allows you to ensure the background process completed before App pool is refreshed. And here is how to use it.

NOTE: QBWI is supported .NET 4.5.2 and above.

Using the Code

From the following sample code, assume GetPayLoad method returns the response within few seconds however due to different reasons, it might take more than the desired response time interval, in this case 5 seconds. Assume also we have the following classes for demostration.

public class Request
{
    public int Id { get; set; }
    public string Content { get; set; }
    // Other properties goes here
}

public class Response
{
    public int Id { get; set; }
    public string Message { get; set; }
    public string PayLoad { get; set; }
    // Other properties goes here
}

using System.Web.Hosting;
// Other namespaces ...
        
public class RequestProcessor
{
    public Response ProcessRequest(Request request)
    {
        Response response = new Response();
        try
        {
            Task<Response> task = new TaskFactory().StartNew(
              () =>
              {
                  return GetPayload(request); // Suppose you have this method in the app
              });

            task.Wait(5000); // Wait 5 seconds
            if (!task.IsFaulted)
            {
                if (!task.IsCompleted)
                {
                    response.Message = "Error";
                    // Ensure the backrground task will be completed before IIS recycles the request
                    HostingEnvironment.QueueBackgroundWorkItem(cancellationToken =>
                    {
                        task.ContinueWith((r) =>
                        {
                            response = r.Result;
                            // Log the background task response
                        });
                    });
                }
                else
                {
                    response = task.Result;
                    response.Message = "Success";
                }
             }
             else
             {
                 response.Message = "Error";
             }
        }
        catch (Exception exception)
        {
            // Log exception
            response.Message = "Error";
        }
        return response;
    }

    public Response GetPayload(Request request)
    {
        Response response = new Response();
        /* Save the data to DB and return the Payload
           Do other things with the request
           ...
           ...
           ...
        */
        response.PayLoad = "Some content";
        return response;
    }
}

You can also utilize CancellationToken to check if IIS or IIS Express forced to be refreshed or closed before recylced itself. i.e.:

if(cancellationToken.IsCancellationRequested)
{
   // Log something like IIS cancelled the operation 
}

History

  • July 29, 2016 : First version 1.0