一个Concurrentdictionary中的更新反映在主字典中 [英] Update in one Concurrentdictionary is reflected in main dictionary

查看:99
本文介绍了一个Concurrentdictionary中的更新反映在主字典中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

I have two concurrent dictionaries say

 ConcurrentDictionary<string, string> MainDic = new ConcurrentDictionary<string, string>();
and

ConcurrentDictionary<string, string> TempDic = new ConcurrentDictionary<string, string>(MainDic);

My TempDic contains same data as MainDic.I do computations on TempDic. whatever changes are made to TempDic is reflected in MainDic. How do i stop this ,i need to keep MainDic as it is for further reference





这里是我的代码:



here is my code:

ConcurrentDictionary<string, DataNetPosition> MainDic = new ConcurrentDictionary<string, DataNetPosition>();
private void GetNetPositionData()
{
    ConcurrentDictionary<string, DataNetPosition> Position;
    if (NetPosFlag == "A")
    {
        foreach (KeyValuePair<string, DataNetPosition> entry in MainDic)
        {
            this.DS.Tables[0].Rows.Add(entry.Value.A, entry.Value.B, entry.Value.C, entry.Value.D);
        }
    }
    else
    {
        Position = new ConcurrentDictionary<string, DataNetPosition>(GetDayPosition(MainDic));
        foreach (KeyValuePair<string, DataNetPosition> entry in Position)
        {
            this.DS.Tables[0].Rows.Add(entry.Value.A, entry.Value.B, entry.Value.C, entry.Value.D);
        }
    }

}

private ConcurrentDictionary<string, DataNetPosition> GetDayPosition(ConcurrentDictionary<string, DataNetPosition> _ALLPos)
{
    var TempDic = new ConcurrentDictionary<string, DataNetPosition>(_ALLPos);
    try
    {
        DataView dv = new DataView(DataSet1.Tables[0]);
        for (int i = 0; i < dv.Table.Rows.Count; i++)
        {
            string NKey = dv.Table.Rows[i][0].ToString() + dv.Table.Rows[i][1].ToString();
            if (TempDic.ContainsKey(NKey))
            {
                var dnp = TempDic[NKey];
                if (dv.Table.Rows[i][2].ToString() == "Buy")
                {
                    dnp.A = dnp.A - Convert.ToDouble(dv.Table.Rows[i]["Qty"]);
                    dnp.B = dnp.B - Convert.ToDouble(dv.Table.Rows[i]["TrdVal"]);
                }
                else
                {
                    dnp.C = dnp.C - Convert.ToDouble(dv.Table.Rows[i]["Qty"]);
                    dnp.D = dnp.D - Convert.ToDouble(dv.Table.Rows[i]["TrdVal"]);
                }
                dnp.E = dnp.E == 0 ? 0 : dnp.B / dnp.A;
                dnp.F = dnp.F == 0 ? 0 : dnp.D / dnp.C;
                dnp.G = dnp.A - dnp.C;
                // other caluculations
                TempDic.TryUpdate(NKey, dnp, null);
            }
        }
    }
    catch (Exception ex)
    {

    }
    return TempDic;
}





如果我的旗帜是A我使用MainDic,因为它是我打电话给



If my flag is A i use MainDic as it is else i call

GetDayPosition

的功能。在

GetDayPosition

函数中,我在TempDic中所做的任何更改都会反映在MainDic中,因此我的原始数据会丢失。我想保留我的数据MainDic。

function whatever changes i do in TempDic is reflected in MainDic as a result my original data is lost. i want to retain my data MainDic.

推荐答案

我的测试确认一个ConcurrentDictionary< string,string>用另一个ConcurrentDictionary的内容初始化它< string,string>正在创建两个独立的ConcurrentDictionaries。



看看:
My test confirms that a ConcurrentDictionary<string,string> which is initialized with the contents of another ConcurrentDictionary<string,string> is creating two independent ConcurrentDictionaries.

Take a look at:
private ConcurrentDictionary<string,> dct1 = new ConcurrentDictionary<string,>();
private ConcurrentDictionary<string,> dct2;

private void TestConcurrent()
{
    dct1.TryAdd("1", "1");
    dct1.TryAdd("2", "2");
    dct1.TryAdd("3", "3");
    dct1.TryAdd("4", "4");
    
    dct2 = new ConcurrentDictionary<string,>(dct1);
    
    dct2["4"] = "5";
    
    dct1["3"] = "6";
}

如果在方法结束时设置断点,并检查两个ConcurrentDictionaries的内部值,您将看到它们之间没有耦合。 />


我会假设,你的'MainDic中的任何变化都不是'TempDic变化的结果,并且两者之间的任何明显同步都是由于你的复制造成的在你的一个线程操作中反复'TempDic into'MainDic。



我希望这种行为是因为,虽然字符串引用类型,它们通常通过值传递。有关此问题的详细讨论,请参阅Jon Skeet的分析[ ^ ]:



Jon Skeet写道:

If you set a break-point at the end of the method, and examine the internal values of both ConcurrentDictionaries, you will see that there is no "coupling" between them.

I would hypothesize, then, that any changes in your 'MainDic are not a result of changes in 'TempDic, and that any apparent synchronization between the two is resulting from your copying 'TempDic into 'MainDic repeatedly in one of your threading operations.

I would expect this behavior because, while strings are a reference Type, they are normally passed by value. For a good discussion of this, see Jon Skeet's analysis [^]:

Jon Skeet wrote:

请注意,许多类型(如字符串)在某些方面都是值类型,但实际上是引用类型。这些被称为不可变类型。这意味着一旦构建了一个实例,就无法更改它。这允许引用类型在某些方面与值类型的行为类似 - 特别是,如果您持有对不可变对象的引用,您可以放心地从方法返回它或将其传递给另一个方法,知识安全它不会在你背后改变。这就是为什么,例如,string.Replace不会更改它被调用的字符串,而是返回一个带有新字符串数据的新实例 - 如果原始字符串被更改,则任何其他变量都包含对字符串的引用会看到变化,这很少是所期望的。
Note that many types (such as string) appear in some ways to be value types, but in fact are reference types. These are known as immutable types. This means that once an instance has been constructed, it can't be changed. This allows a reference type to act similarly to a value type in some ways - in particular, if you hold a reference to an immutable object, you can feel comfortable in returning it from a method or passing it to another method, safe in the knowledge that it won't be changed behind your back. This is why, for instance, the string.Replace doesn't change the string it is called on, but returns a new instance with the new string data in - if the original string were changed, any other variables holding a reference to the string would see the change, which is very rarely what is desired.


bool MainAdd;

           ConcurrentDictionary<string, string> MainDic = new ConcurrentDictionary<string, string>();
           MainDic.TryAdd("0", "Test");

           ConcurrentDictionary<string, string> TempDic =new ConcurrentDictionary<string, string> (MainDic);
           TempDic.TryAdd("1", "Test");

           txtMessage.Text += "\n TempDic Count : " + TempDic.Count.ToString();
           txtMessage.Text += "\n MainDic Count : " + MainDic.Count.ToString();

           MainAdd = MainDic.TryAdd("1", "Test");
           if (!MainAdd)
           {
               txtMessage.Text += "\n Not able to add Duplicate";
               txtMessage.Text += "\n TempDic Count : " + TempDic.Count.ToString();
               txtMessage.Text += "\n MainDic Count : " + MainDic.Count.ToString();
           }
           else
           {
               txtMessage.Text += "\n Added value successfully!";
               txtMessage.Text += "\n TempDic Count : " + TempDic.Count.ToString();
               txtMessage.Text += "\n MainDic Count : " + MainDic.Count.ToString();
           }





不确定你是否想做这样的事情......让我知道。



Not sure if you wanted to do something like this... let me know.


请参阅我对该问题的评论。



显然,如果您需要不相互影响的不同词典中的数据集,请创建两个独立实例的词典,不分享项目。您没有显示导致问题的代码,但我猜您在第二个构造函数的调用时对从一个字典复制到另一个字典的项目执行了某些操作(对于 TempDic )。不要这样做。 If you need \"same data\", clone the elements, or make them immutable.



If you didn’t get it yet, you need to explain more on the purpose of having this two dictionaries, and produce some code sample (short and self-sufficient code sample, not to all your \"real\" project) manifesting this problem.



—SA
Please see my comment to the question.

Apparently, if you need the data sets in different dictionaries not affecting each other, create two independent instances of the dictionaries and don't share the items. You did not show your code causing the problem, but I guess you do something to the items copied from one dictionary to another at the call of the second constructor (for TempDic). Don't do it. If you need "same data", clone the elements, or make them immutable.

If you didn't get it yet, you need to explain more on the purpose of having this two dictionaries, and produce some code sample (short and self-sufficient code sample, not to all your "real" project) manifesting this problem.

—SA


这篇关于一个Concurrentdictionary中的更新反映在主字典中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆