添加 Parallel.Foreach 结果在迭代完成时做一个字典
Adding Parallel.Foreach results do a dictionary when iteration completes
我在这里阅读了一些链接,但我无法找到问题的答案。
我想要实现的是将 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);
据70-483考试参考:
使用并发集合
在多线程环境中工作时,您需要确保不会在没有同步访问的情况下同时操作共享数据。 .NET Framework 提供了一些专为在并发环境中使用而创建的集合 类,这就是您在使用多线程时所拥有的。 这些集合是线程安全的,这意味着它们在内部使用同步来确保它们可以同时被多个线程访问。
这些合集如下:
- 阻塞集合
并发包
ConcurrentDictionary
并发队列
并发堆栈
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 获取项目的当前值(如果可用);如果没有,它会使用工厂方法添加新值。
所以,为了确保您添加了迭代的结果,我会写这样的东西,并且可能会测试我的方法的 return。
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;
}
我在这里阅读了一些链接,但我无法找到问题的答案。
我想要实现的是将 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);
据70-483考试参考:
使用并发集合
在多线程环境中工作时,您需要确保不会在没有同步访问的情况下同时操作共享数据。 .NET Framework 提供了一些专为在并发环境中使用而创建的集合 类,这就是您在使用多线程时所拥有的。 这些集合是线程安全的,这意味着它们在内部使用同步来确保它们可以同时被多个线程访问。
这些合集如下: - 阻塞集合
并发包
ConcurrentDictionary
并发队列
并发堆栈
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 获取项目的当前值(如果可用);如果没有,它会使用工厂方法添加新值。
所以,为了确保您添加了迭代的结果,我会写这样的东西,并且可能会测试我的方法的 return。
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;
}