How does one implement a job queue in .NET?

17,781

Solution 1

What you're likely after is something along the lines of a creator-consumer pattern. this stackoverflow post has a nice implementation of a blocking queue. So you can have multiple threads add things to it, and just one thread forever reading things from it (and it'll block when the queue is empty)

Solution 2

look at either windows workflow http://msdn.microsoft.com/en-us/vstudio/jj684582.aspx or quartz.net http://quartznet.sourceforge.net/

Share:
17,781

Related videos on Youtube

Stephen Booher
Author by

Stephen Booher

Updated on June 04, 2022

Comments

  • Stephen Booher
    Stephen Booher almost 2 years

    I have a Windows service that processes jobs. A job in this service is a sequence of actions, such as:

    A -> B -> C -> D -> E

    Each job is supposed to be completely independent from other jobs. The current implementation processes each job on its own thread (in this case, new System.Threading.Thread), which works well most of the time. However, it turns out that the B action is not thread-safe and two threads should not process the B action at the same time. If two threads try to perform the B action at the same time, strange results or errors are sometimes occurring. Note that the other actions may be executed concurrently by multiple jobs without any ill effects.

    Rather than attempting to re-implement the B action in a thread-safe manner (which I anticipate would require a large amount of resources to implement and test), I would like to just limit each the B action to a single thread at a time.

    Now the obvious initial solution to me was be to put a lock around the B action, which would certainly limit it to a single thread. However, it appears that this solution would not guarantee that all waiting threads will get a chance to process the B action. This is because threads are not guaranteed to queue up in a FIFO or consistent manner. I feel like this could theoretically lead to thread starvation. Thus, I am not comfortable implementing this solution.

    So my question is how can I implement a better (probably FIFO) job queue in .NET that guarantees that all jobs will make it through the B action, one by one?

    My current thought is that I could maintain a some kind of "manager" thread whose job is to pull a job thread from a queue and execute it when the B action is clear. (Perhaps I am describing implementing my own scheduler?) But it seems like that may be rather crude and that perhaps .NET (I'm using .NET 4.0) has better tools in its library for this scenario.

    • paparazzo
      paparazzo over 11 years
      Did you look at BlockingCollection msdn.microsoft.com/en-us/library/dd267312.aspx
    • Marc Gravell
      Marc Gravell over 11 years
      The fact that it isn't strictly FIFO is nit really likely to be a real issue. In reality, all the jobs will make it through just usig lock.
    • Stephen Booher
      Stephen Booher over 11 years
      @MarcGravell I agree with you, mainly on the basis that the service is likely to run out of jobs to run. But I'm still uneasy about it, especially since there doesn't seem to be any mention (that I can find) in the MSDN docs of how threads are queued at lock or Monitor. I would like to avoid jobs having to wait an unfairly long time as well if the system is heavily loaded. Are my fears unfounded?
    • Servy
      Servy over 11 years
      @StephenBooher It depends on the rate of queuing vs the rate of processing. If the processing rate is faster by a sufficient margin the queue will never be long enough consistently enough for it to matter. If the throughput is only barely enough to get by, then starvation is a more serious issue.
    • paparazzo
      paparazzo over 11 years
      If you don't parallel then BlockingCollection will preserve order. I use it this way as at the last queue I insert into SQL and need to preserve order to minimize index fragmentation. And you can set a max size for queue.
  • Servy
    Servy over 11 years
    While that may have been a decent implementation a blocking queue in 09, one has since been added to the language. System.Collections.Concurrent.BlockingCollection
  • Luke
    Luke about 2 years
    If you're using .NET Core / .NET 5+, check out System.Threading.Channels. Here's a great blog post on it: devblogs.microsoft.com/dotnet/…