我已经在这里阅读了一些链接,但无法为我的问题提供答案。
我想要实现的是将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);
答案 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;
}