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

发布于 2024-09-07 01:28:27 字数 2060 浏览 7 评论 0原文

我不确定如何管理此控件的 _namePrefixes 。我知道我可以将其设为非静态,但静态是有意义的,以便在我的项目内容方面此控件的所有使用保持一致。另外,我选择 ObservableCollection 是因为以下场景:

我有 2 台客户端计算机,一台用于标准用途,另一台用于管理选项(管理),例如名称前缀列表。如果客户端正在运行并且管理员进行了更改,则客户端应自行更新并在加载后反映这些更改。哦,因为这是一个 WPF 项目,我想将其数据绑定到列表框。如果这些都不让我使用 ObserableCollection,没什么大不了的......我会使用类似 List 的东西,但我认为这不会改变原来的问题。

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
    }
}

I'm not sure what to do as far as managing the _namePrefixes for this control. I know I can make it non-static, but it makes sense to be static to be consistent across all uses of this control in terms of content for my project. Also, I chose ObservableCollection because of the following scenario:

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
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

本宫微胖 2024-09-14 01:28:27

如果您想要做的是避免由于线程操作重叠而多次将相同的实际实例添加到集合中,那么标准解决方案是在 lock 块内完成工作。

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

(对于后缀也是如此)

锁是一次性资源,因此当一个线程拥有一个对象(在本例中为集合)上的锁时,任何其他尝试获取该锁的线程都将被阻塞,直到现有锁被释放。释放。这种情况的结果是,在任何给定时间只有一个线程能够执行锁块内的代码;所有其他线程将等待,直到当前线程完成,然后一一继续。

值得注意的是,用于锁定的对象不必与块内发生的操作有任何关系。只要锁尝试锁定同一个对象,那么这就会起作用。声明一个 object 类型的专用实例来锁定是一种常见的做法,但在这种情况下,集合可以满足该目的。

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 block.

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

(and the same for suffixes)

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 to lock on, but in this case the collection can serve that purpose.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文