首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >Application.LoadComponent的线程错误(键已存在)

Application.LoadComponent的线程错误(键已存在)
EN

Stack Overflow用户
提问于 2010-03-18 00:03:03
回答 2查看 4.2K关注 0票数 22

MSDN说System.Windows.Application的公共静态成员是线程安全的。但是,当我尝试用多个线程运行我的应用程序时,我得到了以下异常:

代码语言:javascript
代码运行次数:0
运行
复制
ArgumentException: An entry with the same key already exists.

   at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource)
   at System.Collections.Generic.SortedList`2.Add(TKey key, TValue value)
   at System.IO.Packaging.Package.AddIfNoPrefixCollisionDetected(ValidatedPartUri partUri,
        PackagePart part)
   at System.IO.Packaging.Package.GetPartHelper(Uri partUri)
   at System.IO.Packaging.Package.GetPart(Uri partUri)
   at System.Windows.Application.GetResourceOrContentPart(Uri uri)
   at System.Windows.Application.LoadComponent(Uri resourceLocator, Boolean 
bSkipJournaledProperties)
       at System.Windows.Application.LoadComponent(Uri resourceLocator)

异常发生在以下调用中:

代码语言:javascript
代码运行次数:0
运行
复制
genericResources = (ResourceDictionary)Application.LoadComponent(new Uri("/Themes/Generic.xaml", UriKind.Relative));

该应用程序在单个线程上运行良好,甚至在两个或三个线程上运行良好。当我起床超过5点的时候,我每次都会得到错误。我做错了什么吗?我能做些什么来解决这个问题呢?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-03-18 00:59:24

你没有做错什么。MSDN是错误的。Application.LoadComponent实际上并不是线程安全的。在我看来,这是WPF中的一个bug。

问题是,每当Application.LoadComponent从一个“包”加载一个“部分”时,它:

  1. 检查软件包的内部缓存以查看是否已加载该部件,如果找到则返回该部件
  2. 从文件中加载该部件
  3. 将其添加到内部缓存
  4. 将其返回

<代码>G29

您有两个线程调用Application.LoadComponent来同时加载相同的部件。MSDN文档说这没问题,但实际情况是:

  1. 线程#1检查缓存并开始从文件加载
  2. 线程#2检查缓存并开始从文件加载
  3. 线程#1完成从文件加载并添加到缓存
  4. 线程#2完成从文件加载并尝试添加到缓存,导致重复键异常

<代码>G220

此错误的解决方法是将所有对锁的调用包装在一个Application.LoadComponent ()中。

您的锁对象可以在您的App.cs中或其他地方创建(您可以选择):

代码语言:javascript
代码运行次数:0
运行
复制
 public static object MyLoadComponentLock = new Object();

然后,您的LoadComponent调用如下所示:

代码语言:javascript
代码运行次数:0
运行
复制
 lock(App.MyLoadComponentLock)
   genericDictionary = (ResourceDictionary)Application.LoadComponent(...
票数 30
EN

Stack Overflow用户

发布于 2010-03-18 00:09:15

它看起来像是已经在映射中添加了具有相同键的项。这不是线程的问题,而是你的程序的问题。一个线程已经向映射中添加了一个键/值对,而另一个线程正在尝试添加一个具有相同键的值,您是如何在两个单独的线程上拥有相同键的呢?您是如何生成密钥的?

根据创建SortedList时指定的特定IComparer实现,或者根据键本身提供的SortedList实现,按键对IComparable对象的元素进行排序。在这两种情况下,a SortedList都不允许重复的键。

(from the msdn documentation)

更新:

在调用LoadComponent时尝试同步,看看问题是否仍然存在。

我根本不知道他们说下面这些话是什么意思:

此类型的公共静态(在Visual Basic中为Shared)成员是线程安全的。此外,FindResource和TryFindResource方法以及属性和资源属性是线程安全的。

它确实说线程安全,但如果它复制了相同的键,那么它们一定是指其他类型的线程安全。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2463822

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档