I have a asp.net webform which writes about 25-30 items(has info required when user makes follow up request from the form) into a custom cache. Currently all this happens synchronously on the main thread. But at higher loads addcache is becoming a bottleneck.
How can i run this task in the background without consuming threads from the asp.net worker process thread pool.
Alternatives:
Completely async:
Call the server code using AJAX from the client, and add code to monitor the process of the call
I just added an answer related to this process:
https://stackoverflow.com/a/11524718/1268570
Partially async:
The call from the client to the server will be sync which means the response won't be returned to the client until the whole process ends, but the real code will be executed async releasing the thread used by ASP.Net increasing scalability
Execute the page async. You need to implement the IHttpAsyncHandler
interface in your ASPX code behind. This is an example:
public partial class _Default : System.Web.UI.Page, IHttpAsyncHandler
{
public void EndProcessRequest(IAsyncResult result)
{
var context = (result as AsyncOperation).Context;
context.Response.Write(string.Format("<p>End Process Request on {0}</p>", Thread.CurrentThread.ManagedThreadId.ToString()));
}
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
var operation = new AsyncOperation(cb, this.Context, extraData);
operation.StartAsync();
this.Context.Response.Write(string.Format("<p>Begin Process Request on: {0}...</p>", Thread.CurrentThread.ManagedThreadId.ToString()));
return operation;
}
}
public class AsyncOperation : IAsyncResult
{
private AsyncCallback asyncCallback;
public AsyncOperation(AsyncCallback asyncCallback, HttpContext context, object state)
{
this.AsyncState = state;
this.asyncCallback = asyncCallback;
this.Context = context;
this.IsCompleted = false;
this.AsyncWaitHandle = null;
this.CompletedSynchronously = false;
}
public HttpContext Context { get; private set; }
public object AsyncState { get; private set; }
public WaitHandle AsyncWaitHandle { get; private set; }
public bool CompletedSynchronously { get; private set; }
public bool IsCompleted { get; private set; }
public void StartAsync()
{
ThreadPool.QueueUserWorkItem(new WaitCallback(StartAsyncOperation), this.AsyncState);
}
public void StartAsyncOperation(object workItemState)
{
// place here the async logic
this.Context.Response.Write(string.Format("<p>Long Async operation started on: {0}</p>", Thread.CurrentThread.ManagedThreadId.ToString()));
Thread.Sleep(2000);
this.Context.Response.Write(string.Format("<p>Long Async operation ended on: {0}</p>", Thread.CurrentThread.ManagedThreadId.ToString()));
this.IsCompleted = true;
this.asyncCallback(this);
}
}
Output
Create an HttpAsyncHandler. You need to create a custom HttpHandler
implementing the IHttpAsyncHandler
interface. Example:
public class AsyncHandler : IHttpAsyncHandler
{
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
var operation = new AsyncOperation(cb, context, extraData);
operation.StartAsync();
context.Response.Write(string.Format("<p>Begin Process Request on: {0}...</p>", Thread.CurrentThread.ManagedThreadId.ToString()));
return operation;
}
public void EndProcessRequest(IAsyncResult result)
{
var context = (result as AsyncOperation).Context;
context.Response.Write(string.Format("<p>End Process Request on {0}</p>", Thread.CurrentThread.ManagedThreadId.ToString()));
}
public bool IsReusable
{
get { return false; }
}
public void ProcessRequest(HttpContext context)
{
throw new NotImplementedException();
}
}