【问题标题】:Adding Parallel.Foreach results do a dictionary when iteration completes迭代完成时添加 Parallel.Foreach 结果做一个字典
【发布时间】:2018-10-15 17:08:40
【问题描述】:

我在这里阅读了一些链接,但我无法回答我的问题。

我想要实现的是将 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);  

【问题讨论】:

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


    【解决方案1】:

    根据70-483考试参考:


    使用并发集合

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

    这些集合如下: - 阻塞集合

    • 并发包

      ​​>
    • 并发字典

    • 并发队列

    • 并发堆栈

    • 并发字典

    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;
    }
    

    【讨论】:

    • 我明白了,谢谢。也许,使用 ParallelLoopResult 并在返回之前检查一切是否成功完成?该文档对于澄清几点也非常有用。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2013-10-15
    • 1970-01-01
    • 1970-01-01
    • 2017-07-23
    • 1970-01-01
    • 1970-01-01
    • 2022-03-08
    • 2012-12-09
    相关资源
    最近更新 更多