Made small example to choose best scenario for frequent Dictionary update in multithread enviroment. Then have observed "strange" iteration behavior.
using System;
using System.Collections.Generic;
using System.Threading;
namespace DictionaryTest
{
class Program
{
static int _n;
static Dictionary<int, string> _dict = new Dictionary<int, string>();
static void Main(string[] args) {
for (int i = 0; i < 50; i++) _dict[i] = "FIRST";
new Thread(ReadDict).Start();
Thread.Sleep(30);
// CASE A, Throws exception AS EXPECTED.
//_dict.Clear();
// CASE B, ReadDict continues iterate on old dictionary values!!!???
//_dict = new Dictionary<int, string>();
// CASE C
UpdateDict();
ReadDict();
Console.ReadKey();
}
private static void ReadDict() {
// Read Method X
// (continues iterate on old dictionary values!!!???)
//
foreach (var kvp in _dict) {
Thread.Sleep(3);
Console.WriteLine("{0,3} {1,4} {2,6} :{3,5} Method X", Interlocked.Increment(ref _n), kvp.Key, kvp.Value, Thread.CurrentThread.ManagedThreadId);
}
// Read Method Y
//
//for (int i = 0; i < 50; i++) {
// Thread.Sleep(3);
// Console.WriteLine("{0,3} {1,4} {2,6} :{3,5} Method Y", Interlocked.Increment(ref _n), i, _dict[i], Thread.CurrentThread.ManagedThreadId);
//}
}
private static void UpdateDict() {
var tmp = new Dictionary<int, string>();
for (int i = 0; i < 50; i++) tmp[i] = "SECOND";
_dict = new Dictionary<int, string>(tmp);
}
}
}
Combinations:
- CASE A and (Method X or Method Y) - throws Exception as Expected!
- CASE B and Method X - continues iterate on old dictionary values???
- CASE C and Method X - continues iterate on old dictionary values???
- CASE C and Method Y - iterate only Updated values as Expected!
Does foreach
loop take some kind of internal snapshot of static Dictionary member?? If is it so, CASE A also should work but it does not.
Can someone explain what cause this strange behavior?
Edit:
Despite of use of ConcurrentDictionary and code locking, basically my question is about differences between dictionary update methods: to assigne new copy of dictionary as whole new object or better iterate over some collection and update new values seperatly with dict[key]=myObject method? I do not need to keep references to value objects, just replace its.