title: Asynchronous Queue Callback from Web Request
body: <p>I have a web app that talks to web socket thats connected to a third party service.   The socket only has one connection, given that I can have many API calls.  I am adding a message to a message queue and then process one at a time.  I put together a proof of concept below.  I'm struggling with the code that waits for the message to be processed and then calls a delegate with the response.</p>
  <p>The basic goal is I have a message it goes through a message queue, the socket receives and responses, and then a socket message is returned back to the original request.</p>
  <p>Anyone have any ideas for the best approach to wait for a out of context response?</p>
  <p>This is the error I am getting, which I can understand because the message is pushed on the queue and the controller exits.</p>
  <blockquote>
  <p>Unhandled exception. System.ObjectDisposedException:
  IFeatureCollection has been disposed. Object name: 'Collection'.    at
  Microsoft.AspNetCore.Http.Features.FeatureReferences<code>1.ThrowContextDisposed() at Microsoft.AspNetCore.Http.Features.FeatureReferences</code>1.ContextDisposed()
  at
  Microsoft.AspNetCore.Http.Features.FeatureReferences<code>1.Fetch[TFeature](TFeature&amp; cached, Func</code>2 factory)    at
  Microsoft.AspNetCore.Http.DefaultHttpResponse.get_HasStarted()    at
  Microsoft.AspNetCore.Http.HttpResponseWritingExtensions.WriteAsync(HttpResponse
  response, String text, Encoding encoding, CancellationToken
  cancellationToken)    at
  Microsoft.AspNetCore.Http.HttpResponseWritingExtensions.WriteAsync(HttpResponse
  response, String text, CancellationToken cancellationToken)    at
  WebApplication1.Startup.&lt;&gt;c__DisplayClass1_0.&lt;b__2&gt;d.MoveNext()
  in
  C:\Users\martyspc\source\repos\WebApplication1\WebApplication1\Startup.cs:line
  97
  --- End of stack trace from previous location ---    at System.Threading.Tasks.Task.&lt;&gt;c.b__140_1(Object state)<br />
  at System.Threading.QueueUserWorkItemCallbackDefaultContext.Execute()
  at System.Threading.ThreadPoolWorkQueue.Dispatch()    at
  System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()</p>
  </blockquote>
  <pre><code>using Microsoft.AspNetCore.Builder;
  using Microsoft.AspNetCore.Hosting;
  using Microsoft.AspNetCore.Http;
  using Microsoft.Extensions.DependencyInjection;
  using Microsoft.Extensions.Hosting;
  using System;
  using System.Collections.Generic;
  using System.Linq;
  using System.Threading;
  using System.Threading.Tasks;
  
  namespace WebApplication1
  {
      public class MessageProcessor
      {
  
          public void Process()
          {
              while (true)
              {
  
                  try
                  {
                      var message = MessageQueue.GetNextMessage();
  
                      message.ProcessedMessageCallBack(&quot;Hello From Messages&quot;);
                  }
                  catch (Exception ex)
                  {
                      Console.WriteLine(&quot;Message Queue Empty&quot;);
  
  
                  }
  
                  Thread.Sleep(2000);
  
  
              }
          }
  
      }
  
      public static class MessageQueue
      {
  
          private static Queue&lt;Message&gt; Messages { get; set; } = new Queue&lt;Message&gt;();
  
          public static void AddMessage(Message message)
          {
              Messages.Enqueue(message);
          }
  
          public static Message GetNextMessage()
          {
              return Messages.Dequeue();
          }
  
      }
  
      public class Message
      {
          public string Label { get; set; }
          public Action&lt;String&gt; ProcessedMessageCallBack { get; set; }
      }
  
      public class Startup
      {
          // This method gets called by the runtime. Use this method to add services to the container.
          // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
          public void ConfigureServices(IServiceCollection services)
          {
          }
  
          // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
          public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
          {
              if (env.IsDevelopment())
              {
                  app.UseDeveloperExceptionPage();
              }
  
              app.UseRouting();
  
              var mp = new MessageProcessor();
  
              Thread InstanceCaller = new Thread(new ThreadStart(mp.Process));
  
  
              // Start the thread.
              InstanceCaller.Start();
  
              app.UseEndpoints(endpoints =&gt;
              {
                  endpoints.MapGet(&quot;/&quot;, async context =&gt;
                  {
                      Action&lt;string&gt; del = async i =&gt; await context.Response.WriteAsync(&quot;Hi There&quot;);
  
                      MessageQueue.AddMessage(new Message() { Label = &quot;Hello World&quot;, ProcessedMessageCallBack = del });
  
                  });
              });
  
  
          }
      }
  }
  </code></pre>
  <p>Thank you in advance, Marty.</p>