2010-03-17 8 views
20

MSDN dice que los miembros públicos y estáticos de System.Windows.Application son seguros para la ejecución de subprocesos. Pero cuando trato de ejecutar mi aplicación con múltiples hilos que recibo la siguiente excepción:Errores de subprocesamiento con Application.LoadComponent (la clave ya existe)

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) 

La excepción se produce en la siguiente llamada:

genericResources = (ResourceDictionary)Application.LoadComponent(new Uri("/Themes/Generic.xaml", UriKind.Relative)); 

La aplicación funciona bien en un solo hilo e incluso en dos o tres. Cuando me levanto después de 5, obtengo el error cada vez. ¿Estoy haciendo algo mal? ¿Qué puedo hacer para arreglar esto?

+0

Agregado el tag # C .. . Debería llamarte más la atención. – Kiril

+0

Qué bueno. No parece estar arreglado en .NET 4.5. Creado un problema de conexión en https://connect.microsoft.com/VisualStudio/feedback/details/758055/application-loadcomponent-is-not-thread-safe. –

Respuesta

26

No está haciendo algo mal. MSDN está equivocado. Application.LoadComponent no es realmente seguro para subprocesos. Esto es un error en WPF, en mi opinión.

El problema es que siempre Aplicación.LoadComponent carga una "parte" de un "paquete" que:

  1. comprueba su caché interna para el paquete para ver si la pieza ya está cargado & rendimientos si se encuentran
  2. Carga la parte del archivo
  3. lo agrega a la caché interna
  4. lo devuelve

tiene dos hilos de llamada Application.LoadComponent para cargar la misma parte al mismo tiempo. La documentación de MSDN dice que esto está bien, pero lo que está sucediendo es:

  1. Tema # 1 comprueba la caché y empieza a cargar desde el archivo
  2. hilo # 2 comprueba el caché y empieza a cargar desde el archivo
  3. Tema # 1 termina de cargar desde el archivo y agrega a la caché
  4. hilo # 2 termina de cargar desde el archivo y trata de añadir a la caché, lo que resulta en una excepción de clave duplicada

la solución para el Fastidio s para envolver todas las llamadas a Application.LoadComponent dentro de un bloqueo().

Su objeto de bloqueo se puede crear thusly en sus App.cs o en otra parte (a su elección):

public static object MyLoadComponentLock = new Object(); 

Entonces su llamada LoadComponent se parece a esto:

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

Eso es lo que sospechaba, esperaba que estuviera equivocado. – Kelly

+0

+1 Ray, todavía no puedo creerlo aunque ... – Kiril

+2

@Ray ¿archivó un error en http://connect.microsoft.com? – JaredPar

0

Parece que un elemento con la misma clave ya se ha agregado en el mapa. No es un problema de enhebrado, es un problema con el programa que tienes. Un hilo ha agregado un par de clave/valor al mapa y un segundo hilo está intentando agregar un valor con una clave idéntica, ¿cómo terminaste teniendo claves idénticas en dos hilos separados? ¿Cómo estás generando las llaves?

Los elementos de un objeto SortedList están ordenados por cualquiera de las teclas acuerdo con una implementación específica IComparer especificado cuando se crea o de acuerdo con la implementación IComparable proporcionada por las propias teclas de SortedList. En cualquiera de los casos, , SortedList no permite duplicar claves.

(from the msdn documentation)

Actualización:
intente realizar la sincronización cuando se está llamando LoadComponent y ver si el problema persiste.

Simplemente no sé lo que quieren decir cuando dicen lo siguiente:

El estáticos públicos (Shared en Visual Basic) de este tipo son el hilo seguro. Además, los métodos FindResource y TryFindResource y las propiedades de propiedades y recursos son seguros para la ejecución de subprocesos.

Seguro que dice hilo seguro, pero si está duplicando claves idénticas, entonces deben estar refiriéndose a algún otro tipo de seguridad de hilo.

+0

No es mi código el que agrega claves a la lista ordenada. Actualicé la pregunta para mostrar que simplemente estoy llamando a Application.LoadComponent(). – Kelly

Cuestiones relacionadas