迭代完成后,添加Parallel.Foreach结果可做字典

时间:2018-10-15 17:08:40

标签: c# multithreading parallel-processing concurrentdictionary parallel-foreach

我已经在这里阅读了一些链接,但无法为我的问题提供答案。

我想要实现的是将Parallel.ForEach的结果添加到ConcurrentDictionary中。但是,如何确定我要添加迭代结果而不是空值?

我的意思是:我想在操作完成后添加变量。我担心我可能会添加一个空值(即:将不完整的迭代添加到集合中)。

我的代码如下。 谢谢你的提示。

我还读过使用锁比ConcurrentDictionary更快的方法,但我认为就我而言,它不会产生重大变化。

谢谢。

public Dictionary<string,IMagickImage> ComposedImages { get; private set; }
        public ParallelImageComposer(Dictionary<string,MagickImage> InputImages, MagickImage InkZoneImage, int OrientationNumber)
        {

            var resultCollection = new ConcurrentDictionary<string, IMagickImage>();            
            Parallel.ForEach(InputImages, CurrentKeyValuePair =>
            {
                var img = new ImageComposer(InkZoneImage, CurrentKeyValuePair.Value, OrientationNumber).ComposedImage;
                resultCollection.TryAdd(CurrentKeyValuePair.Key, img);
            });            
            ComposedImages = resultCollection.ToDictionary(x => x.Key, x => x.Value);  

1 个答案:

答案 0 :(得分:0)

据70-483考试参考:


使用并发集合

在多线程环境中工作时,需要确保不要在不同步访问的情况下同时操作共享数据。 .NET Framework提供了一些收集类,这些收集类是专门为在并发环境中使用而创建的,这是您在使用多线程时所拥有的。 这些集合是线程安全的,这意味着它们在内部使用同步来确保可以同时被多个线程访问。

这些集合如下:  -BlockingCollection

  • ConcurrentBag

  • ConcurrentDictionary

  • ConcurrentQueue

  • ConcurrentStack

  • ConcurrentDictionary

ConcurrentDictionary以线程安全的方式存储键和值对。您可以使用方法添加和删除项目,并在适当的地方更新项目。

显示您可以在ConcurrentDictionary上使用的方法

var dict = new ConcurrentDictionary<string, int>();

if (dict.TryAdd("k1", 42))
{
    Console.WriteLine("Added");
}

if (dict.TryUpdate("k1", 21, 42))
{
    Console.WriteLine("42 updated to 21");
}

dict["k1"] = 42; // Overwrite unconditionally
int r1 = dict.AddOrUpdate("k1", 3, (s, i) => i * 2);
int r2 = dict.GetOrAdd("k2", 3);

使用ConcurrentDictionary时,您具有可以原子添加的方法, 获取和更新项目。原子操作意味着它将作为一个步骤启动和完成,而不会受到其他线程的干扰。 TryUpdate在更新之前检查当前值是否等于现有值。 AddOrUpdate确保没有添加项目,如果有则将其更新为新值。 GetOrAdd获取项目的当前值(如果有);如果没有,它将使用工厂方法添加新值。


因此,为确保您要添加迭代结果,我将编写类似这样的内容,并可能测试我的方法的返回结果。

public ConcurrentDictionary <string,IMagickImage> ParallelImageComposer(Dictionary<string,MagickImage> InputImages, MagickImage InkZoneImage, int OrientationNumber)
{
    var resultCollection = new ConcurrentDictionary <string,IMagickImage>();

    Parallel.ForEach(InputImages, CurrentKeyValuePair =>
    {
        var img = new ImageComposer(InkZoneImage, CurrentKeyValuePair.Value, OrientationNumber).ComposedImage;

        resultCollection.TryAdd(CurrentKeyValuePair.Key, img);
    });

    return resultCollection;
}