none
.NET 2.0 Application Exception Log - Thread safe? RRS feed

  • Question

  • The documentation says my.application.log is thread safe for shared methods, but not for an instantiation. So when I call WriteException, am I calling a shared method on a class or a non-shared method on an instance?

    The object browser gives this definition for the method:

    Public Sub WriteException(ByVal ex As System.Exception, ByVal severity As System.Diagnostics.TraceEventType, ByVal additionalInfo As String)
    Member of: Microsoft.VisualBasic.Logging.Log
    Summary:
    Writes exception information to the application's log listeners.

    Parameters:
    severity: The type of message. By default, System.Diagnostics.TraceEventType.Error.
    additionalInfo: String to append to the message. By default, this is an empty string.
    ex: Required. Exception to log.


    I'm guessing if this was a shared method, it would show as Public Shared Sub ...., but I'm not sure. Anyone know? Thanks.

    ck
    Saturday, February 28, 2009 5:44 PM

Answers

  • Yes, it would say "Shared" if it was a static method.  The class instance is created the first time you access the My.Application.Log property.  That property getter is not thread-safe.  Best thing to do is to write a "startup" time stamp at program startup before starting any threads.
    Hans Passant.
    • Marked as answer by CrowKing Sunday, March 1, 2009 5:05 AM
    Saturday, February 28, 2009 6:10 PM
    Moderator

All replies

  • Yes, it would say "Shared" if it was a static method.  The class instance is created the first time you access the My.Application.Log property.  That property getter is not thread-safe.  Best thing to do is to write a "startup" time stamp at program startup before starting any threads.
    Hans Passant.
    • Marked as answer by CrowKing Sunday, March 1, 2009 5:05 AM
    Saturday, February 28, 2009 6:10 PM
    Moderator
  • Thanks for the response.

    I'm not sure what you mean by writing a startup time stamp. I'm using the log to document any exceptions thrown throughout my solution (a windows form app and a class lib), so I need something that is thread safe beyond startup. I thought I'd just write a wrapper for My.Application.Log.WriteException that I could lock but then I always have to remember to call it instead.

    Is there a way to hook any calls to My.Application.Log.WriteException to ensure they use my wrapper? Sorry if that's a dumb question but I'm transitioning from VS6 and the .NET frameworks are still a bit new to me. Is it possible to use a delegate to do that? I'll have to read up on them.

    ck
    Sunday, March 1, 2009 5:05 AM
  • Just use the My.Application.Log property once before you start any threads and you'll be okay without any locking.
    Hans Passant.
    Sunday, March 1, 2009 1:18 PM
    Moderator
  • Thanks for your help. I'd like to understand why the non-shared method would be thread safe after instantiation and if there is some kind of general rule that can be applied to other classes in the CLR. I'm not changing any of the properties of the log after the first call, so is it just that my threads don't write to its properties that is making it OK to use, or is it something else?

    ck
    Sunday, March 1, 2009 8:53 PM
  • Under the hood, My.Application.Log uses the TraceSource class.  Tracing through TraceSource is thread-safe.  Similar to how Console::Write() is thread-safe.  Output from two threads is not going to get intermingled within one line of output text.  Internally, the output methods take a lock to ensure this. 

    These are exceptions, the vast majority of .NET classes are not thread-safe.

    Internally, the My.Application.Log property is implemented as a singleton:

    Public ReadOnly Property Log As Log
        Get
            If (Me.m_Log Is Nothing) Then
                Me.m_Log = New Log
            End If
            Return Me.m_Log
        End Get
    End Property

    That is thread-safe only after the m_Log member is initialized.  If it isn't, two threads that access the Log property at the same time could both find the m_Log property to be Nothing and create a new instance.  Only one will survive.  Considering that the TraceSource class is thread-safe, this is arguably a bug.  You avoid getting bit by this by using the Log property once before you start any threads.  That ensures that m_Log is initialized and cannot cause a race.

    You can find more info about the double-checked locking pattern for singletons on this web page.
    Hans Passant.
    Sunday, March 1, 2009 9:48 PM
    Moderator
  •  Thanks, appreciate you taking the time.

    ck
    Sunday, March 1, 2009 11:47 PM