views:

30

answers:

1

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
    }
}
+1  A: 

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.

Adam Robinson
Is there a chance that 2 requests to access the code within that lock could inside that lock somehow? Basically is it possible for the two threads to occur simultaneously that they both activate the lock() at the same time and both enter in by accident?
myermian
@myermian: Nope, that's the whole point of the lock.
Brian Gideon