Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Application.LoadComponent线程错误(密钥已存在)_C#_Wpf_Multithreading_Thread Safety - Fatal编程技术网

C# Application.LoadComponent线程错误(密钥已存在)

C# Application.LoadComponent线程错误(密钥已存在),c#,wpf,multithreading,thread-safety,C#,Wpf,Multithreading,Thread Safety,MSDN表示System.Windows.Application的公共静态成员是线程安全的。但当我尝试使用多个线程运行我的应用程序时,会出现以下异常: ArgumentException: An entry with the same key already exists. at System.ThrowHelper.ThrowArgumentException(ExceptionResource resource) at System.Collections.Generic.So

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));

该应用程序在单个线程上甚至在两个或三个线程上都可以正常工作。当我五点多起床时,我每次都会出错。我做错什么了吗?如何修复此问题?

看起来地图中已经添加了具有相同密钥的项目。这不是线程问题,而是程序的问题。一个线程向映射中添加了一个键/值对,而另一个线程正试图使用相同的键添加一个值,您是如何在两个单独的线程上获得相同的键的?您是如何生成密钥的

SortedList对象的元素 也可以按键进行排序 根据一位特定的IComparer 当 SortedList已创建或根据 可比实现 由钥匙自己提供。在里面 无论哪种情况,分类列表都不会 允许重复密钥。

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

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

公共静态文件(在Visual Studio中共享) 基本)此类型的成员是线程 安全的。此外,FindResource 以及TryFindResource方法和 物业及资源物业 是线程安全的


它当然说线程安全,但如果它复制的是相同的密钥,那么它们一定是指其他类型的线程安全。

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

问题在于,每当Application.LoadComponent从“包”加载“部件”时,它都会:

  • 检查包的内部缓存,查看是否已加载该部件,如果找到,则返回该部件
  • 从文件中加载零件
  • 将其添加到内部缓存
  • 归还
  • 您有两个线程调用
    Application.LoadComponent
    来同时加载同一部分。MSDN文档说明这是可以的,但实际情况是:

  • 线程#1检查缓存并开始从文件加载
  • 线程2检查缓存并开始从文件加载
  • 线程#1完成从文件加载并添加到缓存
  • 线程#2完成从文件加载并尝试添加到缓存,导致重复密钥异常
  • 该错误的解决方法是将对Application.LoadComponent的所有调用封装在锁()中

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

    然后,LoadComponent调用如下所示:

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

    将键添加到排序列表中的不是我的代码。我更新了这个问题,表明我只是在调用Application.LoadComponent()。添加了C#标记。。。应该会引起你更多的注意。多好啊。在.NET4.5中似乎没有被修复。在处创建了连接问题。否。我一直假设微软已经在监控StackOverflow并在内部生成bug报告。如果没有,他们会忽略一个非常有用的QA资源。谢谢你的回答。我们遇到了与原始问题海报几乎完全相同的问题,在MSDN中找到此错误描述无疑为我们节省了数小时的调查时间。我在将同一窗口加载到多个具有不同数据的新线程时遇到了此错误。为了解决这个问题,我在所有新的窗口调用中添加了锁。我再次发现了这个bug。我们正在运行多个dispatcher,当用户双击打开一个新项目时,这会咬到我们,每个项目都在一个新的线程和dispatcher上,然后出现这个错误……多好啊。在.NET4.5中似乎没有被修复。在上创建了连接问题。
     lock(App.MyLoadComponentLock)
       genericDictionary = (ResourceDictionary)Application.LoadComponent(...