Как предотвратить добавление повторяющихся значений в статический поток ObservableCollection безопасно? - PullRequest
0 голосов
/ 25 июня 2010

Я не уверен, что делать с управлением _namePrefixes для этого элемента управления.Я знаю, что могу сделать его нестатичным, но имеет смысл быть статичным, чтобы быть последовательным во всех применениях этого элемента управления с точки зрения контента для моего проекта.Кроме того, я выбрал ObservableCollection из-за следующего сценария:

У меня есть 2 клиентских компьютера, один для стандартного использования, другой для управления параметрами (admin), такими как список префиксов имен.Если клиент работает и администратор вносит изменения, клиент должен обновить себя и отразить эти изменения после того, как он уже был загружен.Да, и потому что это элемент WPF, и я хочу связать его с ListBox.Если ни один из них не заставит меня использовать ObserableCollection, ничего страшного ... Я буду использовать что-то вроде Списка, но я не думаю, что это изменит исходный вопрос.

using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace MyProject
{

    public class NameField : TextBox
    {
        private static ObservableCollection<NamePrefix> _namePrefixes;
        private static ObservableCollection<NameSuffix> _nameSuffixes;

        static NameField()
        {
            _namePrefixes = new ObservableCollection<NamePrefix>();
            _nameSuffixes = new ObservableCollection<NameSuffix>();
        }

        public static void AddNamePrefix(Int32 id, String prefix)
        {
            //TODO: WHAT DO I DO HERE!?
        }

    }

    /// <summary>
    /// A Key/Value structure containing a Name Prefix ID and String value.
    /// </summary>
    public struct NamePrefix
    {
        #region Constructor

        public NamePrefix(Int32 id, String prefix)
            : this()
        {
            ID = id;
            Prefix = prefix;
        }

        #endregion

        #region Properties (ID, Prefix)

        public Int32 ID { get; set; }
        public String Prefix { get; set; }

        #endregion
    }

    /// <summary>
    /// A Key/Value structure containing a Name Suffix ID and String value.
    /// </summary>
    public struct NameSuffix
    {
        #region Constructor

        public NameSuffix(Int32 id, String suffix)
            : this()
        {
            ID = id;
            Suffix = suffix;
        }

        #endregion

        #region Properties (ID, Prefix)

        public Int32 ID { get; set; }
        public String Suffix { get; set; }

        #endregion
    }
}

1 Ответ

2 голосов
/ 25 июня 2010

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

public static void AddNamePrefix(NamePrefix prefix)
{
    lock(_namePrefixes)
    {
        if(!_namePrefixes.Contains(prefix)) _namePrefixes.Add(prefix);
    }
}

(и то же самое для суффиксов)

Блокировки - это одноразовые ресурсы, поэтому, когда поток имеет блокировку для объекта (в данном случае, коллекции), тогда любой другой потокпопытка получить блокировку будет заблокирована, пока не будет снята существующая блокировка.Результатом этого сценария является то, что только один поток сможет выполнить код внутри блока блокировки в любой момент времени;все остальные будут ждать окончания текущего потока, а затем переходят к следующему.

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

...