views:

143

answers:

2

I am using log4net in a class with multiple threads and I had a simple question. Do I need to enter readlock/writelock when checking properties and calling methods on the log4net.ILog interface?

I am using the suggested method from the log4net examples so at the top of said class I have:

Private Shared ReadOnly log As log4net.ILog = log4net.LogManager.GetLogger(decType)

And since the class involves multiple threads interacting with it, I have a ReaderWriterLockSlim instance that I use to make sure I don't get into any race conditions with my variables. So to recap,if I want to make sure I'm practicing safe threading do I need to do something like this:

If Me.ReaderWriterLockSlim.TryEnterUpgradableReadLock(-1) Then
  If log.IsWarnEnabled Then
    If Me.ReaderWriterLockSlim.TryEnterWriteLock(-1) Then
      log.Warn("Log Message Here")
      Me.ReaderWriterLockSlim.ExitWriteLock()
    End If
  End If
  Me.ReaderWriterLockSlim.ExitUpgradeableReadLock()
End If

Or, can I just simply do this:

If log.IsWarnEnabled Then log.Warn("Log Message Here")

P.S. Yes, that is rough pseudo code, I don't actually have an instance of ReaderWriterLockSlim that is named 'ReaderWriterLockSlim'.

+3  A: 

So you basically want to know if log4net thread-safe?

From the FAQ:

Yes, log4net is thread-safe.

So you can simply do this:

If log.IsWarnEnabled Then log.Warn("Log Message Here")
dtb
I wanted to make sure it was still thread safe even when using it as a shared object within a multi-threaded class. I did read that off of the webpage, but since the way I needed to use it seemed like an edge case to me, I wanted to make sure I was still being (thread) safe.
Charles Y.
The definition of "thread safe" (when applied to .NET classes/methods) is "safe to use concurrently from multiple threads". The part about it being a shared object is irrelevant.
Pavel Minaev
If something is called "thread-safe" this means that individual methods can be called on a shared object within a multi-threaded class without additional synchronization code. Of course, if the return value of `IsWarnEnabled` changes between `If` and `Then`, your example may produce unwanted log messages.
dtb
Given the logging message itself is constant, there's no point checking log.IsWarnEnabled. Just make the log.Warn call. log4net will still filter it out if the logger isn't enabled.You only need check IsXXXEnabled if you do something expensive to construct the logging message.
piers7
+1  A: 

In your example above, you don't need to enter the write lock as you aren't changing the value of IsWarnEnabled. Also, there isn't any point in calling TryEnterWriteLock with an infinite timeout - you may as well call ReaderWriterLockSlim.EnterWriteLock. So, even if Log4Net weren't thread-safe (which as others have mentioned, it is), you would just need to write:

readerWriterLock.EnterReadLock();
try
{
  if(log.IsWarnEnabled)
    log.Warn("log message here");
}
finally
{
  readerWriterLock.ExitReadLock();
}

You would then enter a write lock when changing the value of log.IsWarnEnabled.

zcrar70
The point is in the pattern. By following that pattern I can easily implement a timeout value (besides -1) without re-factoring.
Charles Y.
Sure, I just wanted to clear it up for anyone coming here and copy-and-pasting your code :-)
zcrar70
Makes sense, much appreciated Nick!
Charles Y.