Reputation: 104
I've created an application that reads properties from files using the Windows-API-Code-Pack from this package. I'm having an issue when retrieving properties
var width = fileInfo.Properties.GetProperty(SystemProperties.System.Video.FrameWidth).ValueAsObject;
The code breaks here giving me
System.ArgumentException: An item with the same key has already been added.
at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellPropertyFactory.GenericCreateShellProperty[T](PropertyKey propKey, T thirdArg)
at Microsoft.WindowsAPICodePack.Shell.PropertySystem.ShellProperties.GetProperty(PropertyKey key)
This happens mostly when calling this portion of a code in a PLINQ
.AsParallel().WithDegreeOfParallelism(_maxConcurrentThreads).ForAll(...)
even if the degree is set to 1. How can I solve it?
Upvotes: 1
Views: 506
Reputation: 127603
To extend on your existing answer, switching the Dictionary to a ConcurrentDictionary would also solve the problem and remove the need for locks.
private static ConcurrentDictionary<int, Func<PropertyKey, ShellPropertyDescription, object, IShellProperty>> _storeCache
= new ConcurrentDictionary<int, Func<PropertyKey, ShellPropertyDescription, object, IShellProperty>>();
...
private static IShellProperty GenericCreateShellProperty<T>(PropertyKey propKey, T thirdArg)
{
...
Func<PropertyKey, ShellPropertyDescription, object, IShellProperty> ctor;
ctor = _storeCache.GetOrAdd((hash, (key, args) -> {
Type[] argTypes = { typeof(PropertyKey), typeof(ShellPropertyDescription), args.thirdType };
return ExpressConstructor(args.type, argTypes);
}, {thirdType, type});
return ctor(propKey, propDesc, thirdArg);
}
Upvotes: 1
Reputation: 104
Following stuartd suggestion I was able to solve this issue by modifying the source code of the package and adding locks in this code at lines 57 and 62, like this
lock (_storeCache)
{
if (!_storeCache.TryGetValue(hash, out ctor))
{
Type[] argTypes = { typeof(PropertyKey), typeof(ShellPropertyDescription), thirdType };
ctor = ExpressConstructor(type, argTypes);
lock (_storeCache)
_storeCache.Add(hash, ctor);
}
}
Upvotes: 0