C#资源字典XamlParseException - 线程安全性?

3

我正在使用静态资源字典,其初始化方式如下:

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

代码在过去几个月一直运行完美,但在最近几天我开始遇到以下问题:

抛出了“System.Xaml.XamlParseException”类型的异常。 在 System.Windows.Baml2006.Baml2006Reader.ReadObject(KeyRecord record) 处 在 System.Windows.ResourceDictionary.CreateObject(KeyRecord key) 处 在 System.Windows.ResourceDictionary.RealizeDeferContent(Object key, Object& value, Boolean& canCache) 处 在 System.Windows.ResourceDictionary.GetValueWithoutLock(Object key, Boolean& canCache) 处 在 System.Windows.ResourceDictionary.GetValue(Object key, Boolean& canCache) 处

除了上述初始化之外,还可以通过访问所需项来从字典中读取数据。
if (resource.Contains(key))
{
    return resource[key];
}

唯一需要修改的代码可能与多个线程同时访问字典有关。值得一提的是,相同的代码有时可以完美运行,有时会抛出上述异常(非常不一致)。

如果对异常本身或问题有任何见解,我将不胜感激。


2
字典不是线程安全的。不确定为什么会导致 baml 方法抛出异常,但无论问题是什么,您都需要锁定所有多线程字典访问。 - user1228
锁定确实解决了问题,我只是不明白为什么对字典的读取访问会引发这样的异常。 - sagibb
啊,这就是线程错误的表现... - user1228
1个回答

0
一个 ResourceDictionary 和 Dictionary<TKey,TValue> 非常不同。当你从ResourceDictionary 中读取值时,如果给定的键没有缓存值,则会从xaml中解析值。
ResourceDictionary使用的xaml解析器不是线程安全的。在ReadObject方法中(抛出XamlParseException的位置),它首先寻找值所在的xaml读取流中的位置。然后在该位置解析xaml。
如果两个线程同时尝试从ResourceDictionary获取值,则线程A将搜索对象A的位置并开始读取。然后,线程B将在线程A正在读取对象A时将流的读取位置移动到对象B的位置。因此会发生XamlParseException。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接