C# 如何并行遍历动态值字典?

C# 如何并行遍历动态值字典?,c#,multithreading,parallel.foreach,C#,Multithreading,Parallel.foreach,我正在尝试使用dict中值的副本在for-each循环中生成线程 我最初的理解是,foreach将创建一个新的范围,并导致: Dictionary<string, string> Dict = new Dictionary<string, string>() { { "sr1", "1" }, { "sr2", "2" } }; foreach (KeyValuePair<string, string> record in Dict) { new Sy

我正在尝试使用dict中值的副本在for-each循环中生成线程

我最初的理解是,
foreach
将创建一个新的范围,并导致:

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));
}
而不是(预期):

因此,我尝试在foreach中克隆kvp:

KeyValuePair<string, string> tmp = new KeyValuePair<string, string>(record.Key, record.Value);
KeyValuePair tmp=新的KeyValuePair(record.Key,record.Value);
但结果是一样的

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

如何使用线程遍历字典?

问题是,解决方法是在for循环中添加一个局部变量

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));
}
查看函数在第一次运行时如何使用正确版本的
\u recordStored
,但在
\u recordStored
被覆盖后,它将只显示最后的设置值。通过创建局部变量,它不会进行覆盖

想象它的一种方式(我不确定如何在代码示例中表示它)是它创建
\u recordStored1
第一个循环,
\u recordStored2
第二个循环,依此类推。函数在调用函数时使用了正确版本的
\u recordStored

问题是,解决方法是在for循环中添加一个局部变量

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));
}
查看函数在第一次运行时如何使用正确版本的
\u recordStored
,但在
\u recordStored
被覆盖后,它将只显示最后的设置值。通过创建局部变量,它不会进行覆盖


想象它的一种方式(我不确定如何在代码示例中表示它)是它创建
\u recordStored1
第一个循环,
\u recordStored2
第二个循环,依此类推。函数在调用函数时使用了正确版本的
\u recordStored

如果您没有启动计时器,我根本看不出您给出的代码是如何工作的。。。你的字典里有2个词条,而不是你打印出来的4个。如果你能创建一个简短但完整的程序来演示这个问题,那真的会很有帮助。首先,当所有词典条目的值都是1时,为什么它要写1/2/1/2?那么,你为什么要用同一个“sr”键放两个发音条目呢?它会立即抛出..@quetzalcatl哎呀,第二个sr应该是“2”来演示。可能的重复——即使不是完全重复,该链接下的问题完美地描述了问题及其因果关系。请检查一下!我看不出你给出的代码是如何工作的,因为你没有启动计时器。。。你的字典里有2个词条,而不是你打印出来的4个。如果你能创建一个简短但完整的程序来演示这个问题,那真的会很有帮助。首先,当所有词典条目的值都是1时,为什么它要写1/2/1/2?那么,你为什么要用同一个“sr”键放两个发音条目呢?它会立即抛出..@quetzalcatl哎呀,第二个sr应该是“2”来演示。可能的重复——即使不是完全重复,该链接下的问题完美地描述了问题及其因果关系。请检查一下!仅供参考:很好、深入地描述了foreach的自变量的所有问题,甚至还附带了EricLippert的评论;)指针+并发错误很有趣!如果foreach只是一个指针,为什么我需要为它指定一个类型呢。。。如果IIRC改变了foreach的行为,可以使用C#5:)“在C#5中,foreach的循环变量在逻辑上位于循环内部,因此每次闭包都会在变量的新副本上关闭。”@Alex您必须指定类型的原因是因为Dictionary只执行
IEnumerable
而不是
IEnumerable
,我不知道它为什么不执行。此外,它不是指针,指针是一个非常不同的东西,使用
IntPtr
datatype。仅供参考:非常深入地描述了foreach的自动变量的所有问题,甚至还附带了EricLippert的注释;)指针+并发错误很有趣!如果foreach只是一个指针,为什么我需要为它指定一个类型呢。。。如果IIRC改变了foreach的行为,可以使用C#5:)“在C#5中,foreach的循环变量在逻辑上位于循环内部,因此每次闭包都会在变量的新副本上关闭。”@Alex您必须指定类型的原因是因为Dictionary只执行
IEnumerable
而不是
IEnumerable
,我不知道它为什么不执行。此外,它不是指针,指针是一种非常不同的东西,使用
IntPtr
数据类型。
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));
}
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);
}