I have a section of code which should be executed by a maximum number of threads lower than N and also the order in which threads are calling someFunction() should be reflected in the order in which they are entering the section, that is FIFO order.
If I use the Semaphore I have no control over the order in which threads are entering the section.
“There is no guaranteed order, such as FIFO or LIFO, in which blocked
threads enter the semaphore.”
The initial attempt:
class someClass
{
static volatile Semaphore semaphore;
...
someClass()
{
semaphore = new Semaphore(N,N)
}
someType someFunction(InputType input)
{
try
{
semaphore.WaitOne();
/* Section Begins */
var response = someHeavyJob(input); // submitted to the server
return response;
/* Section Ends */
}
finally
{
semaphore.Release();
}
}
}
If I combine a Semaphore and a ConcurrentQueue as follows thread may come back with a response to the request brought by other thread what would require significant changes in other parts of code.
What is the .NET 4.5 solution for the following problem:
- Allow for maximum number of threads lower than N in the section of code
- The order in which threads are entering the section is FIFO
-
Threads will get the response for the request they brought (and not the response to the request brought by other threads)
class someClass { static volatile ConcurrentQueue<someType> cqueue; static volatile Semaphore semaphore; ... someClass() { cqueue = new ConcurrentQueue<someType>(); semaphore = new Semaphore(N,N) } someType someFunction(Request request) { try { cqueue.enqueue(request); semaphore.WaitOne(); Request newrequest; cqueue.TryDequeue(out newrequest); /* Section Begins */ var response = someHeavyJob(Request newrequest); // submitted to the server return response; /* Section Ends */ } finally { semaphore.Release(); } } }
UPDATE:
I am clarifying my question:
SomeHeavyJobs() funciton is a blocking call to the server on which this job is being processed.
UPDATE2:
Thank you all for answers. For the record: I ended up using the FIFO Semaphore
‘If I combine a Semaphore and a ConcurrentQueue as follows thread may come back with a response to the request brought by other thread what would require significant changes in other parts of code.’
I hate to say it, but I would suggest ‘changes in other parts of code’, even though I don’t know how much ‘significance’ this would have.
Typicaly, such a requirement is met as you suggested, by queueing messages that contain a reference to the originating class instance so that responses can be ‘returned’ to the object that requested them. If the originators are all descended from some ‘messagehandler’ class, that makes it easier on the thread that will call the function, (which should be a member of messagehandler). Once the thread/s have performed the function, they can call a ‘onCompletion’ method of the messagehandler. ‘onCompletion’ could either signal an event that the originator is waiting on, (synchronous), or queue something to a private P-C queue of the originator, (asynchronous).
So, a BlockingCollection, one consumer thread and judicious use of C++/C# inheritance/polymorphism should do the job.
Strangely, this is almost exactly what I am being forced into with my current embedded ARM project. The command-line interface thread used for config/debug/log is now so large that it needs a massive 600 words of stack, even in ‘Thumb, Optimize of size’ mode. It can no longer be permitted to call the SD filesystem directly and must now queue itself to the thread that runs the SD card, (which has the largest stack in the system to run FAT32), and wait on a semaphore for the SD thread to call its methods and signal the semaphore when done.
This is the classic way of ensuring that the calls are made sequentially and will cetainly work. It’s basicaly a threadpool with only one thread.
Like the other posters have written, any other approach is likely to be, err.. ‘brave’.