1

I have a queue of tasks or work items that needs to be executed in sequence, in the background. These tasks will be of the "fire and forget" type, meaning that once they are started, I do not really care if they complete or not, no need for cancellation or status update. If they do not complete, the user will be able to retry or diagnose manually.

The goal is to be able to keep a reference to the queue and only have to do

myQueue.Add( () => DoMyStuff() );

in order to add something to the queue.

The System.Threading.Task class only seems to be able to queue tasks one after the other, not by referencing a common queue. I do not want to manage the complexity of getting the latest taks and attach to it.

Threadpools do not guarantee sequencing and will execute work items in parallel. (Which is great, but not what I need)

Is there any built-in class that can handle that that I did not think of?

Edit: We need to be able to add tasks to the queue at a later time. The scenario is that we want to send commands to a device (think switching a light bulb on or off) when the user clicks on a button. The commands take 5 seconds to process and we want the user to be able to click more than once and queue the requests. We do not know upfront how many tasks will be queued nor what will the tasks be.

Vincent Hubert
  • 1,386
  • 9
  • 23
  • 2
    A BackgoundWorker and a Blocking Collection? – Martin James Apr 23 '12 at 19:52
  • I'm not completely sure I understand: why not using a ConcurrentQueue that one single thread (or maybe several) would just myQueue.TryDequeue().Invoke() – PPC Apr 23 '12 at 19:58
  • The attached might be of interest : http://blogs.msdn.com/b/pfxteam/archive/2010/11/21/10094564.aspx – Steve Townsend Apr 23 '12 at 19:58
  • Is there a way to automatically execute the latest task inserted in a blocking collection? I can roll my own queuing/dequeuing/execution mechanism, but I really do not want to reinvent the wheel and it seems like something common enough that a solution would already exist. – Vincent Hubert Apr 23 '12 at 20:14
  • IIRC, you can make the BlockingCollection behave like a stack instead of a queue. – Martin James Apr 25 '12 at 12:21

3 Answers3

3

Create a BlockingCollection, by default it will use a ConcurrentQueue as its internal data structure. Ensure that any task with prerequisites has its prerequisites added to the collection first. The BlockingCollection can be a collection of Tasks, some custom item representing the parameters for a method to be called, a Func<> or Action<> to execute, or whatever. Personally I'd go with either Task or Action.

Then you just need to have a single thread that goes through each item in the collection and executes them synchronously.

You can add new items to the queue while it's working and it won't have any problems.

Servy
  • 202,030
  • 26
  • 332
  • 449
1

You can create a queue object as a wrapper around System.Threading.Task. If you limit the number of concurrently executing threads to just 1 in the underlying thread pool, I think your problem is solved.

Limiting the number of executing tasks: System.Threading.Tasks - Limit the number of concurrent Tasks

Community
  • 1
  • 1
pvoosten
  • 3,247
  • 27
  • 43
-2

How about starting all the threads at the same time and make them listen to a job completion event.

say your threads have id according to the sequence to run, all the threads can start at the same time, but will sleep till they get the job complete/ timeout of the previous job

The Job complete/ timeout event will also help your monitoring thread to keep track of the worker threads

Surya Pratap
  • 495
  • 8
  • 17
  • 2
    What if there are 1 million tasks in the queue? Having threads sleep like this until others finish is really not a good idea in any case. – Steve Townsend Apr 23 '12 at 20:02
  • True, it will be more efficient to use the Background Worker and a blocking collection as mentioned by Martin James – Surya Pratap Apr 23 '12 at 20:11
  • 1
    Honestly every time I see `Sleep` in peoples' code I die a little inside. This is not a comment at you, just in general. Why make that poor thread just sit there doing nothing? There is almost always a better design. – Steve Townsend Apr 23 '12 at 20:16