如何并行迭代动态值字典? [英] How do I iterate through a dynamically valued dictionary in parallel?

查看:62
本文介绍了如何并行迭代动态值字典?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用字典中值的副本在每个循环中生成线程.

I am trying to spawn threads in a for each loop using a copy of the value in a dict.

我最初的理解是 foreach 会创建一个新的作用域,并导致:

My initial understanding was that the foreach would create a new scope, and led to:

Dictionary<string, string> Dict = new Dictionary<string, string>() { { "sr1", "1" }, { "sr2", "2" } };
foreach (KeyValuePair<string, string> record in Dict) {
    new System.Threading.Timer(_ =>
    {
        Console.WriteLine(record.Value);
    }, null, TimeSpan.Zero, new TimeSpan(0, 0, 5));
}

写什么

1
2
2
2

而不是(预期):

1
2
1
2

所以我尝试在 foreach 中克隆 kvp:

So I tried cloning the kvp in the foreach:

KeyValuePair<string, string> tmp = new KeyValuePair<string, string>(record.Key, record.Value);

但这会产生相同的结果.

but that renders the same result.

我也用 System.Parallel.ForEach 尝试过,但这似乎需要非动态值,这对我的字典来说有点像火车粉碎.

I've also tried it with System.Parallel.ForEach but that seems need values that are not dynamic, which is a bit of a train smash for my dictionary.

如何使用线程遍历我的字典?

How can I iterate through my Dictionary with threads?

推荐答案

问题是 closure在你的 lambda 上,修复的方法是在 for 循环中添加一个局部变量

The problem is closure over your lambda, the way to fix is is to add a local variable inside the for loop

Dictionary<string, string> Dict = new Dictionary<string, string>() { { "sr1", "1" }, { "sr2", "2" } };
foreach (KeyValuePair<string, string> record in Dict) {

    var localRecord = record;
    new System.Threading.Timer(_ =>
    {
        Console.WriteLine(localRecord.Value);
    }, null, TimeSpan.Zero, new TimeSpan(0, 0, 5));
}

在您的版本中发生的事情是它捕获了变量 record 而不是 变量的值 记录.因此,当计时器第二次运行时,它使用 record 的当前值",即数组中的第二个元素.

What is happening in your version is it captures the variable record not the value of the variable record. So when the timer runs the 2nd time it uses the "current value" of record which is the 2nd element in the array.

在幕后,这就是您的代码版本中发生的事情.

Behind the scenes this is what is kinda what is happening in your version of the code.

public void MainFunc()
{
    Dictionary<string, string> Dict = new Dictionary<string, string>() { { "sr1", "1" }, { "sr2", "2" } };
    foreach (KeyValuePair<string, string> record in Dict) {

        _recordStored = record;
        new System.Threading.Timer(AnnonFunc, null, TimeSpan.Zero, new TimeSpan(0, 0, 5));
    }
}

private KeyValuePair<string, string> _recordStored;

private void AnnonFunc()
{
    Console.WriteLine(_recordStored.Value);
}

看看你的函数在第一次迭代时如何获得正确版本的 _recordStored,但在 _recordStored 被覆盖后,它只会显示最后设置的值.通过创建局部变量,它不会覆盖.

See how when your function ran it for the first itteration had the correct version of _recordStored, but after _recordStored got overwritten it will only show the last set value. By creating a local variable it does not do that overwriting.

想象它的方法(我不确定如何在代码示例中表示它)是它创建 _recordStored1 第一个循环,_recordStored2 第二个循环,等等.该函数在调用该函数时使用正确版本的 _recordStored#.

A way to imagine it (I am not sure how I could represent it in a code example) is it creates _recordStored1 the first loop, _recordStored2 the 2nd loop, and so on. The function uses the correct version of _recordStored# for when it calls the the function.

这篇关于如何并行迭代动态值字典?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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