Реализация Singleton отлично работает на 32-битной, но не на 64-битной - PullRequest
2 голосов
/ 02 февраля 2010

Я работаю над приложением с общим объектом, доступ к которому осуществляется через одноэлементный файл. Он работает нормально на 32-битной, но на 64-битной не выглядит должным образом блокировки. В конструкторе для моего объекта у меня есть код, который проверяет некоторые конфигурационные ключи reg и запрашивает пользователя, если они не существуют. В 32-разрядной версии я вижу приглашение только один раз, как и ожидалось, однако в 64-разрядной форме приглашение отображается несколько раз. Мой код ниже:

    private static readonly object padlock = new object();
    private static MyClass _instance = null;
    public static MyClass Instance
    {
        get
        {

            lock (padlock)
            {
                if (_instance == null)
                {
                    _instance = new MyClass();
                }
            }
            return _instance;
        }
    }

Любой вклад приветствуется.

Отредактировано Включить образец использования:

    public OtherObject()
    {
        InitializeComponent();

        MyClass.Instance.OtherObjectOrSomething = this;

        this.Load += new System.EventHandler<EventArgs>(OtherObject_Load);
    }

Отредактировано снова Это выполняется внутри надстройки Office. Таким образом, битность определяется установкой офиса. Я определяю конструктор без параметров, который является частным.

Спасибо

Удален слегка анонимизированный конструктор

Ответы [ 6 ]

2 голосов
/ 02 февраля 2010

Это может быть что-то внутреннее в коде конструктора, вызывающее несколько запросов.Представление реестра будет отличаться от 32-разрядного и 64-разрядного процессов, поэтому они могут реагировать на различные внешние условия

0 голосов
/ 03 февраля 2010

В конструкторе для моего объекта у меня есть код, который проверяет некоторые конфигурационные ключи reg и запрашивает пользователя, если они не существуют.

Этодовольно опасная вещь для лениво загруженного статического экземпляра.Можете ли вы гарантировать, что поток пользовательского интерфейса всегда первым использует этот путь к коду?Я не знаю наверняка, что это является частью вашей проблемы, но взаимодействие с пользовательским интерфейсом внутри поточно-ориентированного кода редко является хорошей идеей, и я видел, как в результате происходили разные странные вещи в разных средах.

Можете ли вы переместить этот код пользовательского интерфейса за пределы отложенной загрузки?Если это надстройка Office, то вам нужно подключить событие Startup, которое гарантированно будет выполнено только один раз.Вам даже не нужен код блокировки таким образом, вы можете убедиться, что он инициализирован до того, как какой-либо другой поток попытается его коснуться.

0 голосов
/ 03 февраля 2010

Ваш синглтон ограничивает вас одним экземпляром на домен приложения. Есть ли шанс, что мультипликаторы создаются в нескольких доменах приложений? Вы можете посмотреть на это.

0 голосов
/ 02 февраля 2010

Я собрал реализацию здесь , но по какой-то причине его дважды проголосовали: (

0 голосов
/ 02 февраля 2010

Отличное обсуждение проблем с различными шаблонами реализации синглтона см. В http://www.yoda.arachsys.com/csharp/singleton.html (от Джона Скита).

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

Вот код, который я обычно использую (как в 32-, так и в 64-битных системах):

public sealed class Singleton
{
   private static volatile Singleton instance;
   private static object syncRoot = new object();

   private Singleton()
   {
      // any code that needs to run to create a valid instance of the object.
   }

   public static Singleton Instance
   {
      get
      {
         if (instance == null)
         {
            lock(syncRoot)
            {
               if (instance == null)
               {
                  instance = new Singleton();
               }
            }
         }

         return instance;
      }
   }
}
0 голосов
/ 02 февраля 2010

РЕДАКТИРОВАТЬ: на основе некоторых ответов и комментариев, я вернусь к своему первоначальному ответу.

Я тоже так сделал, за исключением того, что я изменил бы readonly на volatile..

private static volatile object padlock = new object();

Ключевое слово volatile позволяет компилятору знать, что не нужно оптимизировать инструкцию, что обеспечит наличие в поле наиболее актуального значения.

...