Below is a file parser for old style nuget package configuration files. The Parallel.ForEach
is probably overkill; in most cases its fast enough without. However, when using the parallel loop, can I avoid the need for the lock / shared list?
class Program
{
private static readonly object _lock = new Object();
private static readonly List<Package> _packages = new List<Package>();
static void Main(string[] args)
{
string[] files = Directory.GetFiles(Directory.GetCurrentDirectory(), "packages.config", SearchOption.AllDirectories);
Parallel.ForEach(files, GetPackagesForFile);
IEnumerable<IGrouping<string, Package>> idGroups =
_packages.GroupBy(p => p.Id).OrderBy(g => g.Key);
foreach (IGrouping<string, Package> idGroup in idGroups)
{
IEnumerable<IGrouping<string, Package>> versionGroups = idGroup.GroupBy(p => p.Version);
Console.WriteLine($"{idGroup.Key} ({versionGroups.Count()})");
foreach (IGrouping<string, Package> versionGroup in versionGroups)
Console.WriteLine($"\t{versionGroup.Key}");
}
}
private static void GetPackagesForFile(string filepath)
{
var filePackages = XDocument.Load(filepath).Root.Elements("package").Select(GetPackageFromElement);
lock(_lock) _packages.AddRange(filePackages);
}
private static Package GetPackageFromElement(XElement element) =>
new Package(
element.Attribute("id").Value,
element.Attribute("version").Value,
element.Attribute("targetFramework").Value);
}
ConcurrentBag
. \$\endgroup\$ConcurrentBag
has problems with accessing items from different threads. I'd use aConcurrentDictionary<Package, byte>
and just have thebyte
be0
. \$\endgroup\$