How to effectively log asynchronously?

前端 未结 10 1080
无人及你
无人及你 2020-12-07 07:28

I am using Enterprise Library 4 on one of my projects for logging (and other purposes). I\'ve noticed that there is some cost to the logging that I am doing that I can miti

相关标签:
10条回答
  • 2020-12-07 08:08

    I suggest to start with measuring actual performance impact of logging on the overall system (i.e. by running profiler) and optionally switching to something faster like log4net (I've personally migrated to it from EntLib logging a long time ago).

    If this does not work, you can try using this simple method from .NET Framework:

    ThreadPool.QueueUserWorkItem
    

    Queues a method for execution. The method executes when a thread pool thread becomes available.

    MSDN Details

    If this does not work either then you can resort to something like John Skeet has offered and actually code the async logging framework yourself.

    0 讨论(0)
  • 2020-12-07 08:10

    If what you have in mind is a SHARED queue, then I think you are going to have to synchronize the writes to it, the pushes and the pops.

    But, I still think it's worth aiming at the shared queue design. In comparison to the IO of logging and probably in comparison to the other work your app is doing, the brief amount of blocking for the pushes and the pops will probably not be significant.

    0 讨论(0)
  • 2020-12-07 08:16

    An extra level of indirection may help here.

    Your first async method call can put messages onto a synchonized Queue and set an event -- so the locks are happening in the thread-pool, not on your worker threads -- and then have yet another thread pulling messages off the queue when the event is raised.

    0 讨论(0)
  • 2020-12-07 08:18

    I wanted to say that my previous post was kind of useless. You can simply set AutoFlush to true and you will not have to loop through all the listeners. However, I still had crazy problem with parallel threads trying to flush the logger. I had to create another boolean that was set to true during the copying of the queue and executing the LogEntry writes and then in the flush routine I had to check that boolean to make sure something was not already in the queue and the nothing was getting processed before returning.

    Now multiple threads in parallel can hit this thing and when I call flush I know it is really flushed.

         public static void FlushLogs()
        {
            int queueCount;
            bool isProcessingLogs;
            while (true)
            {
                //wait for the current iteration to complete
                m_waitingThreadEvent.WaitOne();
    
                //check to see if we are currently processing logs
                lock (m_isProcessingLogsSync)
                {
                    isProcessingLogs = m_isProcessingLogs;
                }
    
                //check to see if more events were added while the logger was processing the last batch
                lock (m_loggerQueueSync)
                {
                    queueCount = m_loggerQueue.Count;
                }                
    
                if (queueCount == 0 && !isProcessingLogs)
                    break;
    
                //since something is in the queue, reset the signal so we will not keep looping
    
                Thread.Sleep(400);
            }
        }
    
    0 讨论(0)
提交回复
热议问题