ReaderWriterLock with low timeout throws unhandled exception

A

Anders Borum

Hello!

I am working on improving my threading skills and came across a question.
When working with the ReaderWriterLock class, I am getting an unhandled
exception if I acquire a WriterLock with a timeout less than the time
required to process the code section it protects.

The code listed below is just a small application I wrote to check the
behavious of the different threading / synchronization techniques. Basically
the application spins 10 threads with target method that acquires a
WriterLock (timout: 1000 ms) and simulates a long running operation (thread
sleeps for 500 ms).

A third thread that acquired the WriterLock times out, because the previous
two threads spent the available time with a long running process.

The logic answer I can think of is, that if one specifies a timeout, then
the CLR respects that and throws an exception regardless of what's inside
the code section. Handling the thrown exception is a matter of wrapping the
code section (including the acquisition of the WriterLock) in another
try/finally statement .. but that doesn't sound right.

A potential answer is to make sure that the timeout is sufficient for the
operations to complete (e.g. specify an infinite timeout).

...

Here's the error message from the unhandled exception:
An unhandled exception of type 'System.ApplicationException' occurred in
<application>. Additional information: This operation returned because the
timeout period expired.

Please look for "exception is thrown here" in the last method, to see where
I'm getting the exception.

class ThreadDriver
{
static ReaderWriterLock rwl = new ReaderWriterLock();

static void Main(string[] args)
{
Console.WriteLine("Spinning threads ..");

Thread[] threads = new Thread[10];

for (int i = 0; i < 10; i++)
{
Console.WriteLine("Spinning thread #{0}", i);

threads = new Thread(new ThreadStart(Process));
threads.Name = "Thread ID: " + i;
threads.Start();
}

// Initiate join of spinning threads
for (int i = 0; i < 10; i++) { threads.Join(); }

// Calling thread is put on hold ..
Console.WriteLine("Press any key to continue ..");
Console.Read();
}

static void Process()
{
// Acquire lock with a short timeout
rwl.AcquireWriterLock(1000);
try
{
// Identify thread - exception is thrown here
Console.WriteLine(Thread.CurrentThread.Name);

// Simulates a long running process
Thread.Sleep(500);
}
catch (ApplicationException e)
{
Console.WriteLine(Thread.CurrentThread.Name + " failed " +
e.Message);
}
finally { rwl.ReleaseWriterLock(); }
}

I tried googling around looking for a direct answer but couldn't find one.
Not even the threading book from Wrox gives an answer to this (or I haven't
seen it :).

Thanks in advance.
 
J

Jon Skeet [C# MVP]

Anders Borum said:
I am working on improving my threading skills and came across a question.
When working with the ReaderWriterLock class, I am getting an unhandled
exception if I acquire a WriterLock with a timeout less than the time
required to process the code section it protects.

Yes, just as documented in ReaderWriterLock.AcquireReaderLock and
AcquireWriterLock.

I'm not sure why this is a surprise...
 
A

Anders Borum

Hello!

I must have been completely blind last night ..

From the docs: "If the time-out interval expires and the lock request has
not been granted, the method returns control to the calling thread by
throwing an ApplicationException. A thread can catch this exception and
determine what action to take next."

Looking at the sample code in the MSDN written for the ReaderWriterLock, I
didn't see that they're wrapping the AcquireWriterLock in another try/catch
statement. I think I was probably too tired to notice that .. and even
remember, that the AcquireWriterLock need to be in a try statement, if any
exception is to be caught.

static void Process()
{
try
{
// Acquire lock with a short timeout
rwl.AcquireWriterLock(1000);
try
{
// Identify thread - exception is thrown here
Console.WriteLine(Thread.CurrentThread.Name);

// Simulates a long running process
Thread.Sleep(500);
}
catch (ApplicationException e)
{
Console.WriteLine("timeout before acquisition");
}
finally { rwl.ReleaseWriterLock(); }
}
catch (ApplicationException e)
{
// do something with the exception here
}
}

Thanks in advance ..
 
J

Jon Skeet [C# MVP]

Anders Borum said:
I must have been completely blind last night ..

From the docs: "If the time-out interval expires and the lock request has
not been granted, the method returns control to the calling thread by
throwing an ApplicationException. A thread can catch this exception and
determine what action to take next."

Looking at the sample code in the MSDN written for the ReaderWriterLock, I
didn't see that they're wrapping the AcquireWriterLock in another try/catch
statement. I think I was probably too tired to notice that .. and even
remember, that the AcquireWriterLock need to be in a try statement, if any
exception is to be caught.

Well, there's no need for the AcquireWriterLock to be in a try
statement in that particular method - often the correct response will
be to let the exception bubble up the stack.
 
A

Anders Borum

Hello!
Well, there's no need for the AcquireWriterLock to be in a try
statement in that particular method - often the correct response will
be to let the exception bubble up the stack.

That's true, but I was just writing a small app. to illustrate the
behaviour.

Thanks again, Jon!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top