C # Implementing a producer / consumer queue in a web service

I have a pretty vanilla web service (old school asmx). One of the methods starts some asynchronous processing, which does not affect the result returned to the client. Hopefully below will be the snippet below:

[System.Web.Services.WebMethod]
public List<Foo> SampleWebMethod(string id)
{
    // sample db query
    var foo = db.Query<Foo>("WHERE id=@0",id);

    // kick of async stuff here - for example firing off emails
    // dont wait to send result
    DoAsyncStuffHere();

    return foo;

}

My initial implementation of the DoAsyncStuffHere method used ThreadPool.QueueUserWorkItem. So it looks something like this:

public void DoAsyncStuffHere()
{
    ThreadPool.QueueUserWorkItem(delegate
    {
        // DO WORK HERE
    });
}

This approach works great at low loads. However, I need something that can handle a fairly high load. Thus, a producer / consumer sample is likely to be the best way.

, , , -. -?

+3
3

System.Collections.Concurrent.ConcurrentQueue<T> .
, .

( ), , Take(). , .

DoAsyncStuffHere BlockingCollection. System.Threading.Tasks.Task ; Start .

+5

- .

, -.

( Windows Forms, Windows, ..), .

+1

ThreadPool - , ; DoAsyncStuffHere , , , - . , , .

The static constructor ensures that it is called only once, and only one thread should be started (unless there is some strange case with a .NET cache that I don't know about).

Here's the layout for an example - you probably need to implement some locking in the queue and add a bit more complex work to the workflow, but I used this template earlier with success. The object WorkItemmay contain the state of the information that you want to transfer to the workflow.

public static WebService() 
{
  new Thread(WorkerThread).Start();
  WorkQueue = new Queue<WorkItem>();
}

public static void WorkerThread() 
{
  while(true)
  {
    if(WorkQueue.Any()) 
    {
      WorkQueue.Dequeue().DoWork();
    }
    else
    {
      Thread.Sleep(100);
    }
  }
}

public static Queue<WorkItem> WorkQueue { get; set; }

[System.Web.Services.WebMethod]
public List<Foo> SampleWebMethod(string id)
{
  WorkQueue.Queue(newWorkItem());
}
+1
source

All Articles