2015-11-11 6 views
0

У меня есть ASP.net MVC с программой с текущим классом одноэлементным:экземпляра Singleton всегда нуль

public sealed class Foo 
{ 
    private static volatile Foo_instance; 
    private static object syncRoot = new Object(); 
    private List<Obj> _objList; 

    private Foo() 
    { 
     _objList = new List<Obj>(); 
    } 

    public static Foo Instance 
    { 
     get 
     { 
      if (_instance == null) 
      { 
       lock (syncRoot) 
       { 
        _instance = new Foo(); 
       } 
      } 
      return _instance; 
     } 
    } 
    public void AddObjToList(Obj _object) 
    { 
     lock (_instance) 
     { 
      _objList.Add(_object); 
     } 
    } 
    public void FindAndRemoveObj(string id) 
    { 
     lock (_instance) 
     { 
      Obj _object = null; 
      _object= _objList.FirstOrDefault(t => t.UniKey == id); 
      if (_object!= null) 
      { 
       _objList.Remove(object); 
      } 
     } 
    } 
} 

В первый раз, что класс получить экземпляр этого класса он будет возвращать новый/чистый instace из класса foo, как и ожидалось, а затем заполнив список, но второй класс, который удалит itens из того же списка, получит новый экземпляр с пустым списком.

+0

Во-первых, вы должны дважды проверить, что ваше _instance равно null. Чтобы сделать это, вы должны проверить, не потеряно ли значение _instance после блокировки (syncRoot). В противном случае несколько потоков могут закончиться новым. Во-вторых, я бы советовал не применять Singletons таким образом в приложении MVC. Знаете ли вы, что такое статическое время жизни при размещении на веб-сервере? Используйте надлежащую структуру IOC для управления временем лишения времени. –

+0

Похоже, я был ниндзя Фил. Он в основном пишет то же, что и я: «Двойной замок» и не использует статику в IIS. –

+0

Хорошо, поэтому мои знания о двойной проверке были ошибочными. Спасибо за объяснение. Я в настоящее время использую UnityFramework –

ответ

0

Вывод состоит в том, что asp.net создает новые экземпляры домена и каждый раз вызывает новый объект singleton. Я искал, как синхронизировать объекты между доменами, но это слишком «обходное» решение для меня, поэтому я решил добавить булевский столбец, который обновляет значение с подтверждением или сбоем.

Спасибо всем

1

Этот код имеет замок в неположенном месте:

if (_instance == null) 
{ 
    lock (syncRoot) 
    { 
     _instance = new Foo(); 
    } 
} 

Как нить 1 создает _instance, второй поток будет блокировать на замок, а затем создать _instance заново, когда он будет выпущен.

Еще одна вещь, чтобы быть осторожным в этом, что вы никогда не должны полагаться на статические переменные в IIS для поиска по серверу. Пул приложений можно перерабатывать в любое время.

+0

Я удалил блокировку, но экземпляр все еще null для второго потока. Есть ли способ контролировать переработку IIS? –

+0

Утилизация пула приложений настраивается в IIS, но это не является надежным решением вашей проблемы. Почему вы храните эту информацию - нужно ли ее сохранять? Или просто делиться между потоками во время нормальной работы веб-сайта? – Phil

+0

Я отправляю сообщения. Я сохраняю идентификатор сообщения в памяти, ожидая подтверждения того, что получатель выполнил задачу. –