Бросьте NullReferenceException при вызове set_item метода объекта Словаря в сценарии многопоточности

Ответвления темы являются обычно легкими ответвлениями, которые Вы создаете локально и которые имеют имя, которое является понятным для Вы . Они - то, где Вы могли бы сделать работу для исправления ошибки или функции (их также называют ответвлениями функции), который, как ожидают, займет время для завершения.

Другой тип ответвления является "удаленным ответвлением" или "удаленно отслеживающим ответвлением". Этот тип ответвления следует за разработкой кого-то else's работа и хранится в Вашем собственном репозитории. Вы периодически обновляете это ответвление (использующий git fetch) для отслеживания то, что происходит в другом месте. Когда Вы готовы догнать всех изменения else, Вы использовали бы git pull, чтобы и выбрать и объединиться.

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

44
задан Ian Kemp 19 October 2015 в 14:52
поделиться

4 ответа

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

Вам необходимо синхронизировать код в методе GetInstance , чтобы только один поток одновременно обращался словарь .

Редактировать:
Блокируйте доступы по отдельности, чтобы вы не оказались внутри блокировки при выполнении (предположительно) трудоемкой загрузки:

private static object _sync = new object();

public static object GetInstance(string key) {
   object instance = null;
   bool found;
   lock (_sync) {
      found = Instances.TryGetValue(key, out instance);
   }
   if (!found) {
      instance = LoadInstance(key);
      lock (_sync) {
         object current;
         if (Instances.TryGetValue(key, out current)) {
            // some other thread already loaded the object, so we use that instead
            instance = current;
         } else {
            Instances[key] = instance;
         }
      }
   }
   return instance;
}
52
ответ дан 26 November 2019 в 21:58
поделиться

Цитата http://msdn.microsoft.com/en-us/library/xfhwa508.aspx (курсив добавлен мной):

" Thread Safety

Общедоступные статические (общие в Visual Basic) члены этого типа являются потокобезопасными. Любые члены экземпляра не гарантируют безопасность потоков.

A Dictionary <(Of <(TKey, TValue> )>) может поддерживать несколько считывателей одновременно, пока коллекция не изменена. Даже в этом случае перечисление через коллекцию по своей сути не является потокобезопасной процедурой. В редких случаях, когда перечисление соперничает с доступом на запись, коллекция должна быть заблокирована на протяжении всего перечисления. Чтобы разрешить доступ к коллекции нескольким потокам для чтения и записи, вы должны реализовать свою собственную синхронизацию ».

6
ответ дан 26 November 2019 в 21:58
поделиться

Думаю, ваш Экземпляр Словарь не является нулевым. Ваше исключение находится внутри метода Insert - это означает, что во время выполнения существует объект Dictionary (Кроме того, как вы сказали, у вас уже есть TryGetValue раньше, по той же ссылке) Может быть, ваш ключ имеет значение NULL?

EDIT

Только что проверил - TryGetValue выдает исключение ArgumentNullException, когда получает нулевой ключ, и вставляет с нулевым ключом . Но какой класс вы используете в своем примере? Я использовал общий IDictionary , но я вижу, что вы используете не общий. Это класс, унаследованный вами от DictionaryBase или, может быть, HashTable ?

1
ответ дан 26 November 2019 в 21:58
поделиться

Лучшим решением было бы создать синхронизированный словарь. Вот тот, который сработает в этой ситуации. Я считаю, что ReaderWriterLockSlim - лучший объект синхронизации для использования в этой ситуации. Запись в словарь будет довольно редкой. Большую часть времени ключ будет в словаре. Я не реализовал все методы словаря, только те, которые использовались в данном случае, так что это не полный синхронизированный словарь.

public sealed class SynchronizedDictionary<TKey, TValue>
{
    private readonly Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>();
    private readonly ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim();

    public TValue this[TKey key]
    {
        get
        {
            readerWriterLock.EnterReadLock();
            try
            {
                return this.dictionary[key];
            }
            finally
            {
                readerWriterLock.ExitReadLock();
            }
        }
        set
        {
            readerWriterLock.EnterWriteLock();
            try
            {
                this.dictionary[key] = value;
            }
            finally
            {
                readerWriterLock.ExitWriteLock();
            }
        }
    }

    public bool TryGetValue(TKey key, out TValue value)
    {
        readerWriterLock.EnterReadLock();
        try
        {
            return this.dictionary.TryGetValue(key, out value);
        }
        finally
        {
            readerWriterLock.ExitReadLock();
        }
    }
}
1
ответ дан 26 November 2019 в 21:58
поделиться
Другие вопросы по тегам:

Похожие вопросы: