3

次の方法で初期化される静的リソース ディクショナリを使用しています。

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(オブジェクト キー、オブジェクトと値、ブール値と canCache) で System.Windows.ResourceDictionary System.Windows.ResourceDictionary.GetValue(オブジェクト キー、ブール値、canCache) の .GetValueWithoutLock(オブジェクト キー、ブール値、canCache)

上記の初期化とは別に、データは必要な項目にアクセスすることによって辞書から読み取られます。

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

コードへの唯一の変更は、多くのスレッドが同時にディクショナリにアクセスすることに関連している可能性があります。同じコードが完全に機能することもあれば、上記の例外がスローされることもあります (非常に一貫性がありません)。

例外自体または一般的な問題に関する洞察をいただければ幸いです。

4

1 に答える 1

0

ResourceDictionary は Dictionary<TKey,TValue> とは大きく異なります。ResourceDictionary から値を読み取るときに、指定されたキーの値がキャッシュされていない場合は、xaml から値を解析します。

ResourceDictionary で使用される xaml パーサーは、スレッド セーフではありません。ReadObject メソッド (XamlParseException がスローされる場所) では、最初に、値が配置されている xaml 読み取りストリーム内の場所をシークします。次に、その場所で xaml を解析します。

2 つのスレッドが同時に ResourceDictionary から値を取得しようとすると、スレッド A はオブジェクト A の場所を探して読み取りを開始します。スレッド B は、スレッド A がオブジェクト A を読み取っている最中に、ストリームの読み取り位置をオブジェクト B の場所に移動します。そのため、XamlParseException が発生します。

于 2012-02-22T19:40:13.497 に答える