C# 字典<int,对象>自行更新



我会尽量恢复一切:

我有一个类,它用另一个字典的一些元素的初始值创建一个字典(我们叫它二级字典)(为了简单起见,我们叫它主字典,这个类只做一次),然后一个线程每隔x毫秒检查一次主字典,它每隔y毫秒更新一次,检查初始化阶段存储的元素的任何变化。

我的问题是,当我想比较主字典中的element1的值与辅助字典中的element1的值时,它们总是相同的(我理解,直到主字典没有更新,两个值都是相同的,但是当主字典更新时,第二个字典也会立即更新,而不需要我做任何事情)

我已经尝试过concurrentdictionary,使用锁,两者的组合,在初始化函数中创建一个新元素,而不是直接传递它,但似乎没有工作

class Checker
{
private static bool secondaryDictionaryHasChanged = false;
private static ConcurrentDictionary<int, ValueDTO> secondaryDictionary = new ConcurrentDictionary<int, ValueDTO>();
public Checker()
{
initSecondaryDictionary();
Thread checkChangedValsThread = new Thread(() => checkChangedValsThreadFunction(1000));
checkChangedValsThread.Start();
}
public void initSecondaryDictionary()
{
Object MainLock = new Object();
lock (MainLock)
{
Object secondaryLock = new Object();
lock (secondaryLock)
{
foreach (var variable in Maindictionary)
{
if (variable.isElegibleValue)
{
ValueDTO ValueDTOToAdd = new ValueDTO();
ValueDTOToAdd.EligibleVar = variable;
if (variable.contextVariables.Count > 0)
{
List<Var> contextVariablesToAdd = new List<Var>();
foreach (var item in variable.contextVariables)
{
contextVariablesToAdd.Add(getVarFromMainDictionary(item));
}
ValueDTOToAdd.ContextVars = contextVariablesToAdd;
}
secondaryDictionary.TryAdd(ValueDTOToAdd.EligibleVar.varCode, ValueDTOToAdd);
}
}
}
}
secondaryDictionaryHasChanged = false;
}
public void checkChangedValsThreadFunction(int checkTime)
{
while (true)
{
try
{
if (!secondaryDictionaryHasChanged)
{
Thread.Sleep(checkTime);
Object mainLock = new Object();
lock (mainLock)
{
Object secondaryLock = new Object();
lock (secondaryLock)
{
foreach (var item in secondaryDictionary)
{
ValueDTO secondaryDictionaryDTO = item.Value;
Var variableInSecondary = secondaryDictionaryDTO.EligibleVar;
Var variableInMain = getVarFromMainDictionary(item.Value.EligibleVar.varID);
int valueInMain = variableInMain.getIntValue();
int valueInSecondary = variableInSecondary.getIntValue();
if (valueInMain != valueInSecondary)
{
//IT NEVER ENTERS THIS HERE
}
}
}
}
}
}
catch (Exception e)
{
throw new Exception("Some exception: " + e.Message);
}
}
}
}
internal class ValueDTO
{
public Var EligibleVar { get; set; }
public List<Var> ContextVars { get; set; }
}
internal class Var
{
public int varCode { get; set; }
public string varID { get; set; }
}

我添加了一个简化版本的代码问题是它永远不会进入if(mainValue != secondaryValue)

任何关于我哪里出错的帮助或信息将不胜感激

正如fildor已经说过的,您有一个对象和对它的两个引用。为了简化您的问题,我创建了一个简短的示例:

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
public class Example
{
class Person
{
public string Name
{
get;
set;
}
}
public static void Main()
{
var myPerson = new Person();
myPerson.Name = "User1";
var list1 = new List<Person>();
var list2 = new List<Person>();
// put a reference to myPerson into each of the lists
list1.Add(myPerson);
list2.Add(myPerson);
// get the reference to myPerson from list1
var myPersonInList1 = list1[0]
myPersonInList1.Name = "User2";
// this will print User2 because there is only one person object         
Console.WriteLine(list2[0].Name);
}
}

基本上无论你在哪里传递Person,它总是对你创建的Person实例的引用。对它的所有更改都将应用于引用后面的对象。所有引用都指向同一个对象。

一些更深入的知识非常简单,但我希望你能明白:有堆栈和堆存储。栈包含值类型和引用,堆包含对象。

堆栈:

Variable | Value
--------------------
myPerson | @abc123
list1[0] | @abc123
list2[0] | @abc123
myInt    | 42

堆:

Address  | Value
-------------------
abc123   | { Name: "User2" }

现在,每次创建一个指向myPerson的变量时,您只在堆栈中创建一个新条目,指向堆中的同一个对象。现在,当然,当您更新引用后面的对象并将其名称设置为"User1"时,所有引用都会显示更改。