Search code examples
c#.netmultithreadingexceptionqueueuserworkitem

One reader, many writers


Related: How to catch exceptions from a ThreadPool.QueueUserWorkItem?

I am catching exceptions in background threads started by ThreadPool.QueueUserWorkItem(), and propagating them to the main thread via a shared instance variable.

The background threads do this:

try
{
    ... stuff happens here...
}
catch (Exception ex1)
{
    lock(eLock) 
    {
        // record only the first exception
        if (_pendingException == null) 
            _pendingException = ex1;
    }
}

There are multiple potential writers to _pendingException - multiple background threads - so I protect it with a lock.

In the main thread, must I take the lock before reading _pendingException? Or can I simply do this:

if (_pendingException != null)
    ThrowOrHandle(); 

EDIT:
ps: I would prefer to NOT take the lock on the reader thread because it is on the hot path, and I'd be taking and releasing the lock very, very often.


Solution

  • Even though you may only care about the first exception, you may still want to use lock for at least two reasons:

    1. In multi-core CPUs, without making a variable volatile (or performing any memory barrier operation) , there might be a moment when threads running on different cores may see different values. (I am not sure calling lock(queue) in a worker thread will cause any memory barrier operation though). (update) Calling lock(queue) in a worker thread will cause memory barrier operation as pointed out by Eric in the comment below.

    2. Please keep it mind that References are not addresses (by Eric Lippert) (if you are assuming references are 32-bit addresses in 32-bit CLR that can be read atomically). The implementation of references can be changed to some opaque structures that may not be read atomically in future release of CLR (even though I think it is not likely to happen in foreseeable future :)) and your code will break.