readerwriterlockslim (.NET) question

Soldato
Joined
18 Oct 2002
Posts
15,861
Location
NW London
Consider the following pseudocode.

{
Task.Factory.StartNew(() => process(1));

Task.Factory.StartNew(() => process(2));

Task.Factory.StartNew(() => process(3));

Task.Factory.StartNew(() => process(4));
}


private ReaderWriterLockSlim theLock = new ReaderWriterLockSlim();
private List<int> theLock = new List <int> ();

private process(int input)
{
theLock .enterwritelock();
//some complicated process, which takes approximately 10 seconds

container.add(input);
theLock.exitwritelock();
}


Now, am I guaranteed to find the contents of 'container' as follows,

container contents:

1
2
3
4

...or could I possibly get a different order?


I ask this, because I want to do a series of tasks, but I need to know how ReaderWriteLockSlim works: ie. does it queue tasks according to the order they came in, or is possible for a newer task to be processed before an older task, which entered the queue earlier.

Thanks
 
Could be wrong here but ReadWriterLockSlim does not queue the tasks, it's just a method of guaranteeing only one thread is accessing a shared resource at a time.

I believe the Task.Factory is the thing that is actually queueing up your tasks. As for what order the tasks are done in, I've got no idea :)
 
Right gents.

I have just done some tests.

dasyad is correct in that the readerwriterlockslim (or any other form of lock), does not "queue" the tasks.

What this means is that you can start 10 tasks (all waiting on a readerwriterlockslim), to allow access and the tasks will not be allowed access based on the order in which the task requested the lock first. IE. just because task1 requested the enterWriteLock before task2, (if the lock is currently held by task0), task1 may not be the next task to get access to the lock.

I just did a quick test and found that I did not get the sequence: 1 2 3 4. Instead, I got a jumbled up sequence.

I'm going to get around this problem by creating a thread which monitors the contents of a queue and only submits a new task (held in the queue), when the previous task has released the readerwriterlockslim. This way, each task shall be carried out in the same order that it was submitted (to the queue).

It kind of sucks, because 5 lines of code will now have to be replaced by 100+ lines of code.
 
So do you need the tasks 1, 2, 4, 5 to be done in order?

Yep.

They have to be run in their own threads, they have to be run in the same order that they were started and locks must be in place so that 1 task cannot access a method until the previous task has completed its work.
 
http://www.albahari.com/threading/

I found that to be a helpful resource on threading.

For your problem I guess there is loads of potential solutions, you could in theory start up the 1st thread, wait till it finishes then spawn the 2nd etc. which would be made easier if you extended the BackgroundWorker as shown in some of the examples in the link.

I think that the essence of your problem is that you need to know when task x has finished in order to then proceed with task y, so a construct that uses that behaviour would help you big time.
 
Last edited:
I'm going to use a queue system.

When ever a new task is submitted, rather than it being done immediately, it shall be submitted into a queue.

Meanwhile a background thread is going to monitor the queue. If it finds that there is a task in the queue, it shall extract it from the queue and submit it to the method (which the task was originally bound for).

What the above means is that multiple threads can add tasks to the queue, without any worry that tasks are going to be completed out of sequence.

This system shall also prevent multiple threads attempting to access a single method (which would inevitably lead to out-of-sequence processes, as shown in my example above).

I've never tried out concurrent queues, but having just read up on this (thanks humble coder), the ConcurrentQueueis ideal in this scenario.

Thanks gents.
 
Unless each thread that launches is also responsible for checking for outstanding work on the queue and waking up another thread to handle it (most likely by notifying the caller through a progress update, rather than attempting to take this on directly, which would be a nightmare), then I have not seen any other mechanism by which you could reliably be sure a thread has actually started doing what it needs to do before the next one fires.

Otherwise it's entirely feasible to have this scenario:

You tell thread1 to start
You tell thread2 to start
Thread2 starts
Thread2 finishes its work
Thread1 starts
Thread1 finishes its work

Worst case scenario, but it can happen. Even if it doesn't happen on your machine, your CPU, with any other machine and any other CPU it can.

It also means of course, that just starting a thread (and even if it really does start doing stuff) before another does not give you any amount of predictability over the order they finish either.
 
Last edited:
Unless each thread that launches is also responsible for checking for outstanding work on the queue ...

No can do.

Some calls on a method (call it Method1) are being made by the program, automatically. While some calls on Method1 are being made by human beings, when they choose.

It is impossible, to "lock" a human being out of a method. They press a button and they expect the command to be followed (or at least submitted into a queue for processing).

Another point is that the locks do not guarantee the FIFO sequence/order. I have no choice but to use a queue system.
 
Essentially each item will be running entirely in serial then, it'll be multithreaded from the point of view of being non-blocking to the end user(s), but the background work is all serialised.

That's fine, just making sure you weren't trying to control multiple background thread sequences running in parallel, and hopefully performance isn't critical for the tasks that running them in serial works out.
 
... it'll be multithreaded from the point of view of being non-blocking to the end user(s), but the background work is all serialised.

That's it.

What I don't want to do is lock up the GUI and essentially, the entire application by running it non threaded.
 
Back
Top Bottom