c# - Application.LoadComponent 的线程错误( key 已存在)

标签 c# wpf multithreading thread-safety

MSDN 说 System.Windows.Application 的公共(public)静态成员是线程安全的。但是当我尝试使用多线程运行我的应用程序时,出现以下异常:

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 点时,我每次都会收到错误消息。难道我做错了什么?我该怎么做才能解决这个问题?

最佳答案

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

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

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

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

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

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

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

 public static object MyLoadComponentLock = new Object();

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

 lock(App.MyLoadComponentLock)
   genericDictionary = (ResourceDictionary)Application.LoadComponent(...

关于c# - Application.LoadComponent 的线程错误( key 已存在),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2463822/

相关文章:

multithreading - 如何使用多线程进行 zlib 压缩

c# - 防止最大化的 WPF 窗口覆盖任务栏

c# - 进程线程名称

c# - 使用Dapper查询MySql数据库时,InvalidCastException

wpf - View 不能被多个 Listview 共享

安卓 : Retrofit Callback success and failure executed asynchronously?

c# - 字符串加密/解密密码 c# Metro Style

wpf - XamlReader 生成 DataTemplate 的问题

c# - 将 DependencyProperty 转发到用户控件中包含的控件

java - Thread.sleep() 是否不让其他线程运行?