2

Dans une application WPF, un thread BackgroundWorker créait un objet. Appelons l'objet foo.InvalidOperationException sur un objet à partir d'un thread exécuté

Code de travail de fond:

SomeClass foo = new SomeClass(); 
// Do some operation on foo 

// Set some dependency property on the main class to foo 
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, 
    (SendOrPostCallback)delegate { SetValue(FooProperty, foo); }, 
    foo); 

Maintenant, quand la classe principale tente d'accéder FooProperty à l'aide d'un getter, je reçois un InvalidOperationException: Le thread appelant ne peut pas accéder à cet objet parce qu'un autre thread est propriétaire.

Si le thread créer l'objet est terminé, pourquoi possède-t-il toujours l'objet? Y-a-t-il moyen de faire autrement.?

Répondre

2

Un objet que vous créez dans un thread donné appartient à ce thread. C'est pourquoi vous obtenez une exception InvalidOperationException. Si vous souhaitez définir une propriété dans un thread d'arrière-plan, je recommande que le délégué renvoie la valeur souhaitée et appelle SetValue à partir de votre thread principal. (thread qui a créé l'objet).

+0

J'ai essayé d'effectuer le paramètre dans le rappel RunWorkerCompleted, mais j'ai besoin que le thread principal attende à un certain endroit dans un constructeur jusqu'à ce que le paramètre ait été fait. Bien sûr, cela bloque l'exécution entière et le rappel RunWorkerCompleted n'est jamais exécuté.Existez-vous une meilleure pratique pour faire de l'exécution "attendre"? –

+0

Votre droit.Tout les attentes doivent être faites dans le thread d'arrière-plan.Si le constructeur doit w Pour un certain réglage à faire, je suggère de prendre cette attente sur le constructeur (si possible) et de l'appeler dans votre fil de fond. – helios456

1

La grande majorité des objets dans WPF ont une affinité de thread. Une fois créé sur un thread particulier, un objet WPF ne fonctionnera que s'il est utilisé à partir de ce thread. Cette restriction est appliquée (contrairement à WinForms) sur pratiquement toutes les opérations que vous effectuez sur cet objet.

Vous devrez modifier votre code pour que Foo soit créé sur le thread d'interface utilisateur réel de ce scénario.

1

En supposant que SomeClass dérive de DispatcherObject, le thread qui l'a créé exécute la pompe de message chargée du traitement des messages pour l'objet foo. Par conséquent, si ce thread se termine, l'objet ne peut plus traiter les messages, ce qui n'est pas une bonne idée.

Dans la plupart des cas, vous devez utiliser le même thread d'interface utilisateur pour créer tous vos objets d'interface utilisateur (ou tout autre élément dérivé de DispatcherObject et assurez-vous qu'il s'exécute pendant la durée de votre application.

Questions connexes