代码之家  ›  专栏  ›  技术社区  ›  myermian

如何防止在静态ObservableCollection线程安全中添加重复值?

  •  0
  • myermian  · 技术社区  · 15 年前

    我不知道如何管理这个控件的前缀。我知道我可以使它成为非静态的,但是在我的项目的内容方面,在这个控件的所有使用中保持一致是有意义的。另外,我选择ObservableCollection是因为以下场景:

    I have 2 client machines, one for standard use, the other for managing options (admin) such as a Name Prefix list. If the client is running and the admin makes a change, the client should update itself and reflect those changes after it has already been loaded. Oh, and because this is a WPF item and I wanna databind it to a ListBox. If neither of these make me use an ObserableCollection, no big deal... I'll use something like a List, but I don't think that'll change the original question.

    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 回复  |  直到 15 年前
        1
  •  2
  •   Adam Robinson    15 年前

    If what you're looking to do is avoid adding the same actual instance to the collection multiple times because of threaded operations overlapping, then the standard solution for this is to do the work inside of a lock 块。

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

    (后缀也一样)

    Locks are single-use resources, so when a thread has a lock on an object (in this case, the collection), then any other thread attempting to acquire the lock will be blocked until the existing lock is released. The upshot in this scenario is that only one thread will be able to execute the code inside the lock block at any given time; all others will wait until the current thread finishes, then proceed on one by one.

    It's worth noting that the object used to lock does not have to have anything to do with the operations taking place inside of the block. As long as the locks attempt to lock on the same object, then this will work. It's a common practice to declare a dedicated instance of type object 锁定,但在这种情况下,集合可以用于此目的。