How Thread-Safe is NLog?

后端 未结 6 1961
慢半拍i
慢半拍i 2020-12-02 23:23

Well,

I have waited for days before deciding to post this issue, as I was not sure how to state this, resutling into a long detailed post. However, I think it is re

6条回答
  •  情歌与酒
    2020-12-02 23:42

    I don't know NLog, but from what I can see from the pieces above and the API docs(http://nlog-project.org/help/), there is only one static configuration. So if you want to use this method to add rules to the config only when the logger is created (each from a different thread), you're editing the same configuration object. As far as I can see in the NLog docs, there is no way to use a separate configuration for each logger, so that is why you need all the rules.

    The best way to add the rules would be to add the rules before you start the async workers, but I'm going to assume that that is not what you want.

    It would also be possible to just use one logger for all the workers. But I'm going to assume that you need every worker in a separate file.

    If each thread is creating their own logger and adding their own rules to the configuration, you'll have to put a lock around it. Note that even with you synchronizing your code, there is still a chance that some other code is enumerating over the rules while you are changing them. As you show, NLog does not do locking around these bits of code. So I presume any thread-safe claims are for the actual log-writing methods only.

    I'm not sure what your existing lock does, but I don't think it is not doing what you intended. So, change

    ...
    lock (LogManager.Configuration.LoggingRules)
    config.LoggingRules.Add(Rule);                
    
    LogManager.Configuration = config;
    logger = LogManager.GetLogger(loggerID);
    
    return logger;
    

    to

    ...
    lock(privateConfigLock){
        LogManager.Configuration.LoggingRules.Add(Rule);                
    
        logger = LogManager.GetLogger(loggerID);
    }
    return logger;
    

    Note that it is considered a best practice to only lock objects that you 'own', i.e. that are private to your class. This prevents that some class in some other code (that does not adhere to the best practice) locks on the same code that may create a deadlock. So we should define privateConfigLock as private to your class. We should also make it static, so that every thread sees the same object reference, like so:

    public class Logging{
        // object used to synchronize the addition of config rules and logger creation
        private static readonly object privateConfigLock = new object();
    ...
    

提交回复
热议问题