title: How to send multiple acknowledgement to client using IHttpAsyncHandler in asp.net
body: <p>I have implemented IHttpAsyncHandler in my class to perform 5-6 long running process in background and acknowledge to client on start of each task.</p>
  
  <p>Earlier I was using one session variable and updating it with current status of task, and giving async call request to server from jquery in interval of 5 seconds to get current status, but this implementation is not good because its continually hitting request to server for status.</p>
  
  <p>Then I implemented IHttpAsyncHandler in my application, now server itself send acknowledgement to client, but as per my implementation I am able to send only one acknowledgement! if I try to send more than one then its giving error as "object reference not set to an instance of an object" </p>
  
  <p>please check my sample code.</p>
  
  <p><strong>in my code 
  ExecuteFirst() method works fine sending acknowledgement to client but ExecuteSecond() does not send acknowledgement its giving error.</strong></p>
  
  <p>I goggled a lot but not getting proper way to send multiple acknowledgement to client.</p>
  
  <p>this is my sample code, please help me if any one have any idea.</p>
  
  <p><strong>Javascript</strong> </p>
  
  <pre><code>function postRequest(url) {
  
          var url = 'StartLongRunningProcess.ashx?JOBCODE=18'
  
          var xmlhttp = getRequestObject();
  
          xmlhttp.open("POST", url, true);
  
  
          xmlhttp.onreadystatechange =
                      function () {
  
                          if (xmlhttp.readyState == 4) {
                              var response = xmlhttp.responseText;
                              divResponse.innerHTML += "&lt;p&gt;" + response + "&lt;/p&gt;";                             
                          }
                      }
  
  
          xmlhttp.send();
  
      }
  
  
  
   function getRequestObject() {
          var req;
  
          if (window.XMLHttpRequest &amp;&amp; !(window.ActiveXObject)) {
              try {
                  req = new XMLHttpRequest();
              }
              catch (e) {
                  req = false;
              }
          }
          else if (window.ActiveXObject) {
              try {
                  req = new ActiveXObject('Msxml2.XMLHTTP');
              }
              catch (e) {
                  try {
                      req = new ActiveXObject('Microsoft.XMLHTTP');
                  }
                  catch (e) {
                      req = false;
                  }
              }
          }
  
          return req;
      }
  </code></pre>
  
  <p><strong>StartLongRunningProcess.ashx.cs</strong></p>
  
  <pre><code>public class StartLongRunningProcess: IHttpAsyncHandler, IRequiresSessionState
  {
  
              private AsyncRequestResult _asyncResult;
      public void ProcessRequest(HttpContext context) {}
  
      public bool IsReusable
      {
          get { return true;}
      }
  
  
      public IAsyncResult BeginProcessRequest(HttpContext context, System.AsyncCallback cb, object extraData)
      {
  
          int32 jobCode= convert.ToInt32(context.Request["JOBCODE"]);
          _asyncResult = new AsyncRequestResult(context, cb, jobCode);
  
                    if(jobCode==18)
                    {
  
                     StartProcess18()
  
                    }
                    else
                    {
  
                     //StartProcessOther()
  
                    }
  }
  
  
  
              private StartProcess18()
              {
  
                  var task1= new Task(() =&gt;
                  {
                       ExecuteFirst();                           
                  });
  
  
                  var task2 = task1.ContinueWith((t1) =&gt;
                  {
                      ExecuteSecond();
                  }, TaskContinuationOptions.OnlyOnRanToCompletion);
  
                  task1.Start();
              }
  
  
  
      private ExecuteFirst()
      {
  
            //notify to client that this job has been started
           _asyncResult.CurrentContext.Response.Write("First task has been started"); 
           _asyncResult.Notify();
  
           // Above line of code successfully send a acknowledgement to client 
  
           //Doing some long running process
      }
  
  
      private ExecuteSecond()
      {
  
            //notify to client that this job has been started
           _asyncResult.CurrentContext.Response.Write("Second task has been started"); 
  
            // Above line of code giving error and if I skip it and call Notify() this also does not work.
  
           _asyncResult.Notify();
  
  
           //Doing some long running process
      }
  
      public void EndProcessRequest(IAsyncResult result)
  {
  
  }
  
  
   }
  </code></pre>
  
  <p><strong>AsyncRequestResult.cs</strong> </p>
  
  <pre><code>public class AsyncRequestResult : IAsyncResult 
  {
      private HttpContext context;
      private AsyncCallback callback;     
  
      private ManualResetEvent completeEvent = null;
      private object data;
      private object objLock = new object();
      private bool isComplete = false;        
  
      public AsyncRequestResult(HttpContext ctx, AsyncCallback cb, object d)
      {
          this.context = ctx;
          this.callback = cb;
          this.data = d;
      }
  
      public HttpContext Context
      {
          get { return this.context; }
      }
  
      public void Notify()
      {
          //isComplete = true;
  
  
          lock(objLock)
          {
              if(completeEvent != null)
              {
                  completeEvent.Set();
              }
          }
  
  
          if (callback != null)
          {
              callback(this);
          }
      }
  
  
      public object AsyncState
      {
          get { return this.data; }
      }
  
  
      public bool CompletedSynchronously
      {
          get { return false; }
      }
  
  
      public WaitHandle AsyncWaitHandle
      {
          get
          {
              lock(objLock)
              {
                  if (completeEvent == null)
                      completeEvent = new ManualResetEvent(false);
  
                  return completeEvent;
              }
          }
      }
  
  
      public bool IsCompleted
      {
          get { return this.isComplete; }
      }
  
  }
  </code></pre>