2

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.

Community
  • 1
  • 1
Stephen Booher
  • 6,522
  • 4
  • 34
  • 50
  • 1
    Did you look at BlockingCollection http://msdn.microsoft.com/en-us/library/dd267312.aspx – paparazzo Jan 03 '13 at 18:15
  • 1
    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. – Marc Gravell Jan 03 '13 at 18:20
  • @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? – Stephen Booher Jan 03 '13 at 18:33
  • @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. – Servy Jan 03 '13 at 19:11
  • 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. – paparazzo Jan 03 '13 at 19:12

2 Answers2

2

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)

Community
  • 1
  • 1
PhonicUK
  • 13,486
  • 4
  • 43
  • 62
  • 8
    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` – Servy Jan 03 '13 at 19:10
  • If you're using .NET Core / .NET 5+, check out `System.Threading.Channels`. Here's a great blog post on it: https://devblogs.microsoft.com/dotnet/an-introduction-to-system-threading-channels/ – Luke Mar 23 '22 at 12:23
1

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

pm100
  • 48,078
  • 23
  • 82
  • 145