【问题标题】:Code isn't iterating over the whole Dictionary?代码没有遍历整个字典?
【发布时间】:2016-09-21 03:43:23
【问题描述】:

我偶然发现了一个问题,但我不知道自己做错了什么。我尝试了无数不同的东西,但由于某种原因它不起作用。我的主循环:

static Dictionary<string, int> dict = new Dictionary<string, int>();

public static void IterateOverEachUser()
{
    if (dict.Count > 0) {
        foreach (KeyValuePair<string, int> item in dict.ToList())
        {
            string userName = item.Key;
            int amountLeft = item.Value;
            if(amountLeft == 60)
            {
                Log(userName + " started!");
            }
            Log(userName + amountLeft);
            dict[userName] = dict[userName] - 1;
            amountLeft = item.Value;
            if(amountLeft == 0)
            {
                Log(userName + " ran out!");
            }
        }
    }
}

public static void AddUser(string User)
{
    if (dict.ContainsKey(User))
    {
        Log("User already exists.");
    }
    else
    {
        dict.Add(User,60);
        Log("User has been added.");
    }
}

我每 5 秒循环一次 IterateOverEachUser()。当我使用该方法添加一个用户时,一切都很好,但是当我添加第二个用户时,他的值停留在 60,而另一个继续滚动。

有人知道为什么会这样吗?我来自使用 HashMaps 的 Java,并使用相同的代码按预期工作。 (即:每个用户都被迭代,所有用户的值都减1,然后停止,直到5秒循环再次调用IterateOverEachUser()方法)。

提前致谢!

【问题讨论】:

  • 我被否决了,但我没有得到任何建设性的批评?就我而言,我的代码应该可以完美运行,对吧?我发布了自己的代码,展示了我进行了广泛的研究,解释了我的问题并解释了我期望代码做什么。这不值得一票否决.. imo
  • 小心,您在循环遍历字典时正在修改字典。在大多数语言中,这可能是一个问题
  • @HoàngLong 感谢您的反馈!我也想过这个问题,但不幸的是添加“.ToList()”并不能解决问题。另外,您是否知道一种更好的方法来避免在字典运行时对其进行编辑?
  • 您是否遇到任何错误/异常?
  • 代码本身运行良好 (this dotNetFiddle)。这正是您应该提供minimal reproducible example 的原因。您的问题出在其他地方。

标签: c# dictionary iteration


【解决方案1】:

amountLeft = item.Value; 会产生错误的值(旧值)。

此外,在使用计时器和静态资源时,最好使用lock 使您的方法线程安全

下面的测试代码非常适合我:

static Dictionary<string, int> dict = new Dictionary<string, int>();
static object lockObject = new Object();

public static void IterateOverEachUser()
{
    lock (lockObject)
    {
        if (dict.Count > 0)
        {
            foreach (KeyValuePair<string, int> item in dict.ToList())
            {
                string userName = item.Key;
                int amountLeft = item.Value;
                if (amountLeft == 60)
                {
                    Console.WriteLine(userName + " started!");
                }
                Console.WriteLine(userName + amountLeft);
                dict[userName] = dict[userName] - 1;
                amountLeft = dict[userName];
                if (amountLeft == 0)
                {
                    Console.WriteLine(userName + " ran out!");
                }

                Console.WriteLine("User " + item.Key + " = " + amountLeft);
            }
        }
    }
}

public static void AddUser(string User)
{
    if (dict.ContainsKey(User))
    {
        Console.WriteLine("User already exists.");
    }
    else
    {
        dict.Add(User, 60);
        Console.WriteLine("User has been added.");
    }
}

static void Main(string[] args)
{

    AddUser("U1");
    AddUser("U2");

    int counter = 1;
    System.Timers.Timer t1 = new System.Timers.Timer();
    t1.Interval = 5000;
    t1.Elapsed += (oo, ee) => 
    {
        IterateOverEachUser();

        if (counter++ == 5)
            AddUser("U3");
    };

    t1.Start();

    Console.ReadKey();
}

输出:

User has been added.
User has been added.
U1 started!
U160
User U1 = 59
U2 started!
U260
User U2 = 59
U159
User U1 = 58
U259
User U2 = 58
U158
User U1 = 57
U258
User U2 = 57
U157
User U1 = 56
U257
User U2 = 56
U156
User U1 = 55
U256
User U2 = 55
User has been added.
U155
User U1 = 54
U255
User U2 = 54
U3 started!
U360
User U3 = 59
U154
User U1 = 53
U254
User U2 = 53
U359
User U3 = 58
U153
User U1 = 52
U253
User U2 = 52
U358
User U3 = 57
// and so one

【讨论】:

  • 锁定对象效果很好!猜猜我将不得不深入研究文档并了解有关线程的更多信息。非常感谢您的回答,也感谢所有做出贡献的人!
猜你喜欢
  • 1970-01-01
  • 2010-11-20
  • 1970-01-01
  • 2019-09-24
  • 2017-05-23
  • 1970-01-01
相关资源
最近更新 更多