Словарь ресурсов C# XamlParseException - Безопасность потока?

Я использую статический словарь ресурсов, который инициализируется следующим образом:

static ResourceDictionary resource = new ResourceDictionary() 
{ 
    Source = new Uri(
        "pack://application:,,,/CommonResources;component/ApplicationData.xaml") 
};

Код работал отлично в течение последних нескольких месяцев, но в последние несколько дней у меня возникла следующая проблема:

Исключение типа "System.Xaml.XamlParseException" было сгенерировано. в System.Windows.Baml2006.Baml2006Reader.ReadObject(запись KeyRecord) в System.Windows.ResourceDictionary.CreateObject(ключ KeyRecord) в System.Windows.ResourceDictionary.RealizeDeferContent(ключ объекта, объект & значение, Boolean& canCacheR) в System.Windows.ictionary.GetValueWithoutLock(ключ объекта, Boolean& canCache) в System.Windows.ResourceDictionary.GetValue(ключ объекта, Boolean& canCache)

Помимо вышеуказанной инициализации, данные считываются из словаря путем доступа к необходимому элементу:

if (resource.Contains(key))
{
    return resource[key];
}

Единственная модификация кода может быть связана с одновременным доступом к словарю многих потоков. Также важно упомянуть, что один и тот же код иногда работает отлично, а иногда выдает вышеприведенное исключение (очень непоследовательное).

Буду признателен за любые идеи относительно самого исключения или проблемы в целом.

1 ответ

ResourceDictionary очень отличается от словаря. Когда вы читаете значение из ResourceDictionary, если у него нет кэшированного значения для данного ключа, оно будет анализировать значение из xaml.

Анализатор xaml, используемый ResourceDictionary, не является потокобезопасным. В методе ReadObject (где выбрасывается исключение XamlParseException) он сначала ищет местоположение в потоке чтения xaml, в котором находится значение. Затем он анализирует XAML в этом месте.

Если два потока попытаются получить значение из ResourceDictionary одновременно, поток A будет искать местоположение объекта A и начнет чтение. Затем поток B переместит позицию чтения потока в местоположение объекта B, в то время как поток A находится в середине чтения объекта A. И таким образом вы получите исключение XamlParseException.

Другие вопросы по тегам