Value Types and Dictionary Search

The class below raises an event for each registered new "dataKey" and raises an event when "dataKey" is canceled and it is considered that "dataKey is zero.

This class is designed to become thread safe, and I try to make it as possible as possible.

My question is: in the Deregister method, can I somehow remove the second search when I update the value (_data [dataKey] = currentCountValue;)?

I cannot just update the current variable currentCountValue, because the value is updated only in the local stack, not in the dictionary.

Or can you recommend any performance improvements? I don’t think I can remove the lock and use the CAS (Interlocked methods) operations to update the counter, since the dictionary is not thread safe for updates when used like this ... right?

/ I am using C # 3.0.

Thank you for your time.

public sealed class DataCounter
{
    public event EventHandler NewKeyEvent;
    public event EventHandler ZeroCountEvent;
    private readonly Dictionary<string, int> _data = new Dictionary<string, int>();

    public void Register(string dataKey)
    {
        lock (_data)
        {
            if (_data.ContainsKey(dataKey))
            {
                _data[dataKey]++;
            }
            else
            {
                _data.Add(dataKey, 1);
                if (NewKeyEvent != null) NewKeyEvent(this, null);
            }
        }
    }

    public void Deregister(string dataKey)
    {
        lock (_data)
        {
            int currentCountValue;
            if (_data.TryGetValue(dataKey, out currentCountValue))
            {
                if (currentCountValue > 0)
                {
                    currentCountValue--;
                    _data[dataKey] = currentCountValue;
                }

                if (currentCountValue == 0)
                {
                    if (ZeroCountEvent != null) ZeroCountEvent(this, null);
                }
            }
        }
    }
}
+3
source share
3 answers

As a thought - if you do not want to do a “set” using an indexer, can you move the counter to a class?

class CounterBox {
    public int Count {get;set;}
}

Then we have a Dictionary<string,CounterBox>. Now you can update Countoutside the dictionary and only call Remove(dataKey)when it .Countis zero. This will have an additional de-link, but you will not need to assign using an indexer.

: .

- :

public sealed class DataCounter
{
    private class CounterBox
    {
        public int Count { get; set; }
    }
    public event EventHandler NewKeyEvent;
    public event EventHandler ZeroCountEvent;
    private readonly Dictionary<string, CounterBox> _data
        = new Dictionary<string, CounterBox>();

    public void Register(string dataKey)
    {
        lock (_data)
        {
            CounterBox box;
            if (_data.TryGetValue(dataKey, out box))
            {
                box.Count++;
            }
            else
            {
                _data.Add(dataKey, new CounterBox { Count = 1 });
                EventHandler handler = NewKeyEvent;
                if (handler != null) handler(this, EventArgs.Empty);
            }
        }
    }

    public void Deregister(string dataKey)
    {
        lock (_data)
        {
            CounterBox box;
            if (_data.TryGetValue(dataKey, out box))
            {
                if (box.Count > 0)
                {
                    box.Count--;
                }

                if (box.Count == 0)
                {
                    EventHandler handler = ZeroCountEvent;
                    if (handler != null) handler(this, EventArgs.Empty);
                    _data.Remove(dataKey);
                }
            }
        }
    }
}
+2

.

// Execute this ...
if (NewKeyEvent != null)

// ... other threads remove all event handlers here ...

// ... NullReferenceException here.
    NewKeyEvent(this, null);

.

EventHandler newKeyEvent = this.newKeyEvent;

 if (newKeyEvent != null)
 {
     newKeyEvent(this, null);
 }
0

, ( - , ).

. , . , , , , , , , .

, , - , (, ). , , , .

, , , ( , ).

0

Source: https://habr.com/ru/post/1708072/


All Articles