Как исправить ArgumentException в Windows-API-Code-Pack? - PullRequest
1 голос
/ 11 апреля 2019

Я создал приложение, которое считывает свойства из файлов, используя Windows-API-Code-Pack из этого пакета. У меня проблема с получением свойств

var width = fileInfo.Properties.GetProperty(SystemProperties.System.Video.FrameWidth).ValueAsObject;

Код ломается здесь, давая мне

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)

Это происходит в основном при вызове этой части кода в PLINQ

.AsParallel().WithDegreeOfParallelism(_maxConcurrentThreads).ForAll(...)

, даже если степень установлена ​​на 1. Как я могу ее решить?

Ответы [ 2 ]

1 голос
/ 12 апреля 2019

Чтобы расширить существующий ответ, переключение словаря на ConcurrentDictionary также решит проблему и устранит необходимость в блокировках.

    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);
    }
0 голосов
/ 12 апреля 2019

Следуя предложению stuartd Я смог решить эту проблему, изменив исходный код пакета и добавив блокировки в этот код в строках 57 и 62, как это

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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...