在ASP.NET中锁定Singleton + Builder模式。使构建器模式安全线程

时间:2015-03-30 09:02:17

标签: asp.net .net thread-safety singleton builder

我正面临着让我发疯的奇怪情况。 我有一个Class MyApplication.cs

public class MyApplication 
{
    private static volatile MyApplication _instance;
    private static object syncRoot = new Object();
    private Logger logger=new Logger();

    static public MyApplication Instance
    {
        get
        {
            if (_instance == null)
            {
                lock (syncRoot)
                {
                    if (_instance == null)
                        _instance = new MyApplication ();
                }
            }
            return _instance;

        }

      public void Load(){
         logger.setId("100").setMessage("Load succesful").Write();
      }


}

它有单例模式。

我还有一个带有Builder模式的 Logger.cs 类:

    public class Logger
    {
         private string Id="NOT_SET";
         private string Message;

         public Logger setId(int id){
             this.Id=id;
         }
         public Logger setMessage(string message){
             this.Message=message;
         }
         public void Write(){
              if(Id="NOT_SET"){
                throw Exception("NOT SET EXCEPCION");  
              }
              //write output staff
         }

}

问题:我的ASP.NET应用程序的每个页面加载,MyApplication Load()方法都被调用。因此,每次请求都会创建一个新的Logger对象。

Page_load(){
   MyApplication.Instance.Load();
}

事实是我有时会得到NOT_SET_EXCEPTION。 可能是因为某些并发访问MyApplication中的Logger变量导致它被我无法理解的原因重置。

  • 您怎么看?
  • 如何安全地使用Logger变量?

  • 在这种情况下使用构建器模式是个坏主意吗?

最好锁定创建过程直到它结束,因为如果没有记录变量从不同的线程中被修改。 请帮忙

1 个答案:

答案 0 :(得分:0)

正如xanatos建议我创建了一个新类LoggBuilder(),线程安全代码现在也在一个锁内,所以方法

  • Id()
  • 消息()
  • 写()

    立即执行。

    public class LoggerBuilder
    {
    private static object syncRoot = new Object();
    
    Logger logger;
    int eventId;
    string message;
    
    
    public LoggerBuilder(Logger logger)
    {
        this.logger = logger;
    }
    
    public LoggerBuilder EventId(int EventId)
    {
        this.eventId = EventId;
        return this;
    }
    
    
    public LoggerBuilder Message(string Message)
    {
        this.message = Message;
        return this;
    }
    
    
    public void Write()
    {
        lock (syncRoot)
        {
            logger.EventId(this.eventId);
            logger.Message(this.message);
            logger.Write();
        }
    }
    

    } }