void DoRaiseInBackground( object unusedState )
{
int raisedCount = 0;
bool again;
do
{
again = false;
// This lock guaranties that no more than one event will fire at the same time.
// Since we capture the errors to raise from inside it, it also guaranties that
// listeners will receive errors in order.
lock( _raiseLock )
{
Interlocked.Exchange( ref _dispatchWorkItemIsReady, 0 );
ErrorEventArgs e = CreateEvent();
if( e != null )
{
raisedCount += e.LoggingErrors.Count;
// Thread-safe (C# 4.0 compiler use CompareExchange).
var h = OnErrorFromBackgroundThreads;
if( h != null )
{
// h.GetInvocationList() creates an independent copy of Delegate[].
foreach( EventHandler<ErrorEventArgs> d in h.GetInvocationList() )
{
try
{
d( this, e );
}
catch( Exception ex2 )
{
// Since this thread will loop, flags it to avoid
// creating useless new dispatching queue items.
Interlocked.Exchange( ref _dispatchWorkItemIsReady, 1 );
Interlocked.Increment( ref _waitingRaiseCount );
OnErrorFromBackgroundThreads -= (EventHandler<ErrorEventArgs>)d;
lock( _collector )
{
if( _collector.Count == _collector.Capacity ) Interlocked.Increment( ref _lostErrorCount );
else _collector.Push( new Error( Impl.CoreResources.ErrorWhileCollectorRaiseError, ex2, _seqNumber++, _lostErrorCount ) );
}
again = true;
}
}
}
}
}
}
while( again );
// Signals the _endOfWorkLock monitor if _waitingRaiseCount reached 0.
if( Interlocked.Add( ref _waitingRaiseCount, -raisedCount ) == 0 )
{
lock( _endOfWorkLock ) Monitor.PulseAll( _endOfWorkLock );
}
}