简体   繁体   中英

Simple logging class in C#

I am trying to create my own logging class (don't want to use any side libraries). My application will send log requests from various classes, various threads and my main goal is to keep it queued properly and shown to user. With my current approach it looks a bit weird (as you can see I have to reasssure 2 times, that the LogWork was invoked properly).

public class Logger
{
    private static Logger mInstance;
    private LogLevel mLogLevel;
    private Queue<LogEntry> mLogQueue;
    private static readonly object mSyncObject = new object();


    public async void Log(LogLevel logLevel, string logMessage)
    {
        LogEntry le = new LogEntry(logLevel, logMessage, DateTime.Now);
        mInstance.mLogQueue.Enqueue(le);
        await Task.Run(() => LogWork(logLevel, logMessage));
    }


    private void LogWork(LogLevel logLevel, string logMessage)
    {
        lock (mSyncObject)
        {
            if (mLogQueue.Count > 0)
            {
                LogEntry le = mLogQueue.Dequeue();
                if (le != null)
                {
                    ShowLog(le);
                }
            }
        }
    }

    (...)
}

However that's not what I was aiming for. If I understand multithreading properly, my snippet will create a new thread for every log request and wait until mSyncObject becomes unlocked. How could I change it so there is one thread waiting for some logs to come? Is this even the correct approach?

Looking forward for any suggestions

Try using the Monitor.Wait , and Monitor.Pulse . You're writing a "consumer" from the producer-consumer pattern, there's a good wiki on it. Wait waits for control to be passed back to the thread on the lock object, pulse notifies threads waiting for control of the lock object.

From here on I'll refer to Monitor.Wait colloquially as "wait" or wait(obj) and Monitor.Pulse as "notify" or notify(obj).

Here's how that would work:

1 - The LogWork thread waits to be notified inside the lock.

2 - The process creating the log notifies the LogWork thread when a log is added.

3 - LogWork checks for new LogEntry's, and if there are any, it does the logging.

4 - LogWork notifies, then goto step 1.

private void LogWork(...)
    lock(mSyncObject) {
        Monitor.Pulse(mSyncObject);
        while(Monitor.Wait(mSyncObject)) {
            if (mLogQueue.Count != 0) {
                LogEntry le = queue.dequeue();
                // handle log here
            }
            Monitor.Pulse(mSyncObject);
        }
    }
}

The snippet from where the log is created (the log "producer") would look like:

lock(mSyncObject) {
    Monitor.Wait(mSyncObject);
    mLogQueue.enqueue(myLogEntry);
    Monitor.Pulse(mSyncObject);
}

If you have many classes which all need to produce logs, then it may be prudent to have them inherit a Log method from a LogProducer class which encapsulates the waiting and notifying.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM