MSDN说System.Windows.Application的公共静态成员是线程安全的。但是,当我尝试用多个线程运行我的应用程序时,我得到了以下异常:
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)
异常发生在以下调用中:
genericResources = (ResourceDictionary)Application.LoadComponent(new Uri("/Themes/Generic.xaml", UriKind.Relative));
该应用程序在单个线程上运行良好,甚至在两个或三个线程上运行良好。当我起床超过5点的时候,我每次都会得到错误。我做错了什么吗?我能做些什么来解决这个问题呢?
发布于 2010-03-17 16:59:24
你没有做错什么。MSDN是错误的。Application.LoadComponent实际上并不是线程安全的。在我看来,这是WPF中的一个bug。
问题是,每当Application.LoadComponent从一个“包”加载一个“部分”时,它:
<代码>G29
您有两个线程调用Application.LoadComponent
来同时加载相同的部件。MSDN文档说这没问题,但实际情况是:
<代码>G220
此错误的解决方法是将所有对锁的调用包装在一个Application.LoadComponent ()中。
您的锁对象可以在您的App.cs中或其他地方创建(您可以选择):
public static object MyLoadComponentLock = new Object();
然后,您的LoadComponent调用如下所示:
lock(App.MyLoadComponentLock)
genericDictionary = (ResourceDictionary)Application.LoadComponent(...
发布于 2010-03-17 16:09:15
它看起来像是已经在映射中添加了具有相同键的项。这不是线程的问题,而是你的程序的问题。一个线程已经向映射中添加了一个键/值对,而另一个线程正在尝试添加一个具有相同键的值,您是如何在两个单独的线程上拥有相同键的呢?您是如何生成密钥的?
根据创建SortedList时指定的特定IComparer实现,或者根据键本身提供的SortedList实现,按键对IComparable对象的元素进行排序。在这两种情况下,a SortedList都不允许重复的键。
更新:
在调用LoadComponent
时尝试同步,看看问题是否仍然存在。
我根本不知道他们说下面这些话是什么意思:
此类型的公共静态(在Visual Basic中为Shared)成员是线程安全的。此外,FindResource和TryFindResource方法以及属性和资源属性是线程安全的。
它确实说线程安全,但如果它复制了相同的键,那么它们一定是指其他类型的线程安全。
https://stackoverflow.com/questions/2463822
复制