线程错误与Application.LoadComponent(键已经存在) [英] Threading errors with Application.LoadComponent (key already exists)
问题描述
MSDN说System.Windows.Application的公共静态成员是线程安全的。但是,当我尝试使用多线程我得到下面的异常运行我的应用程序:
的ArgumentException:与已经同键的条目存在。
在System.ThrowHelper.ThrowArgumentException(ExceptionResource资源)
在System.Collections.Generic.SortedList`2.Add(TKEY的关键,TValue值)
在System.IO。 Packaging.Package.AddIfNoPrefixCollisionDetected(ValidatedPartUri partUri,
的PackagePart一部分)
在System.IO.Packaging.Package.GetPartHelper(URI partUri)
在System.IO.Packaging.Package.GetPart(URI在System.Windows.Application.LoadComponent partUri)
在System.Windows.Application.GetResourceOrContentPart(URI URI)
(URI resourceLocator,布尔
bSkipJournaledProperties)
在System.Windows。 Application.LoadComponent(URI resourceLocator)
在下面的调用发生异常:
genericResources =(ResourceDictionary中)Application.LoadComponent(新的URI(/主题/ Generic.xaml,UriKind.Relative));
应用程序工作正常,在单个线程,甚至在两个或三个。当我起身过去5然后我得到的错误每次。难道我做错了什么?我能做些什么来解决这个问题?
您不是做错了什么。 MSDN是错误的。 Application.LoadComponent实际上不是线程安全的。这是在WPF中的错误,在我看来
现在的问题是,每当Application.LoadComponent从一个包加载部分是:
<醇>
您有两个线程调用 Application.LoadComponent
来加载相同的部分与此同时。 MSDN文档说,这是好的,但正在发生的事情是:
- 线程#1检查缓存,并开始从文件加载LI>
- 线程#2检查缓存,并开始从文件加载
- 线程#1完成从文件加载,并增加了高速缓存
- 线程#2完成从文件加载并尝试添加到缓存中,从而导致重复键异常
对于错误的解决方法是换锁()里面Application.LoadComponent所有来电。
您锁定对象可正是如此在App.cs或其他地方创建(你的选择):
公共静态对象MyLoadComponentLock =新的对象();
那么你LoadComponent调用看起来是这样的:
锁(App.MyLoadComponentLock)
genericDictionary =(ResourceDictionary中)Application.LoadComponent(...
MSDN says that public static members of System.Windows.Application are thread safe. But when I try to run my app with multiple threads I get the following exception:
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)
The exception occurs on the following call:
genericResources = (ResourceDictionary)Application.LoadComponent(new Uri("/Themes/Generic.xaml", UriKind.Relative));
The application works fine on a single thread and even on two or three. When I get up past 5 then I get the error every time. Am I doing something wrong? What can I do to fix this?
You are not doing something wrong. MSDN is wrong. Application.LoadComponent is not actually thread safe. This is a bug in WPF, in my opinion.
The problem is that whenever Application.LoadComponent loads a "Part" from a "Package" it:
- Checks its internal cache for the package to see if the part is already loaded & returns it if found
- Loads the part from the file
- Adds it to the internal cache
- Returns it
You have two threads calling Application.LoadComponent
to load the same part at the same time. The MSDN documentation says this is ok, but what is happening is:
- Thread #1 checks the cache and starts loading from the file
- Thread #2 checks the cache and starts loading from the file
- Thread #1 finishes loading from the file and adds to the cache
- Thread #2 finishes loading from the file and tries to add to the cache, resulting in a duplicate key exception
The workaround for the bug is to wrap all calls to Application.LoadComponent inside a lock().
Your lock object can be created thusly in your App.cs or elsewhere (your choice):
public static object MyLoadComponentLock = new Object();
Then your LoadComponent call looks like this:
lock(App.MyLoadComponentLock)
genericDictionary = (ResourceDictionary)Application.LoadComponent(...
这篇关于线程错误与Application.LoadComponent(键已经存在)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!