2010-04-19 5 views
1

J'essaie d'appeler Dispatcher.PushFrame() de plusieurs thread différent mais rencontrer une erreur:WPF - Dispatcher PushFrame()

Must create DependencySource on same Thread as the DependencyObject.

Voici un extrait de code:

_lockFrame = new DispatcherFrame(true); 
Dispatcher.PushFrame(_lockFrame); 

Lorsque J'ai essayé:

Dispatcher.CurrentDispatcher.Invoke(
    DispatcherPriority.Normal, 
    new Action(() => _lockFrame = new DispatcherFrame(true)); 
Dispatcher.PushFrame(_lockFrame); 

Je reçois l'erreur:

Objects must be created by the same thread.

Quelle est l'approche pour pousser plusieurs trames dans le Dispatcher à partir de threads différents?

Répondre

1

Chaque thread a son propre répartiteur objet - retourné par Dispatcher.CurrentDispatcher

L'approche serait de mettre en cache l'objet répartiteur cible une fois en appelant la méthode ci-dessus sur l'interface utilisateur de cette discussion. Ensuite, utilisez _cachedObj.Invoke comme vous l'avez - pour le déplacer vers le bon thread.

L'interface utilisateur de WPF a une 'affinité de thread' - l'interface utilisateur n'est accessible que par le thread qui la crée.

Mise à jour: Vous n'êtes pas sûr de ce que vous essayez d'obtenir. Mais l'extrait de code suivant a fonctionné pour moi.

private Dispatcher _dispatcher; 
    private DispatcherFrame _lockFrame; 
    public Window1() 
    { 
     InitializeComponent(); 

     _dispatcher = Dispatcher.CurrentDispatcher; 

     // the other thread 
     Thread t = new Thread(
      (ThreadStart)delegate 
      { 

       _dispatcher.Invoke(
        (Action)delegate 
        { 
         var frame = CreateNewFrame(); 
         Dispatcher.PushFrame(frame); 
        }); 
      }); 
     t.Start(); 
+0

J'ai essayé ceci mais continue à obtenir les objets doivent être créés par le même fil. Erreur. –

+0

@Tri Q: voir mise à jour. Je ne sais pas si votre problème peut être résolu avec une approche différente si ... le code ci-dessus me fait grincer des dents. – Gishu

+0

Qu'y a-t-il dans CreateNewFrame()? Est-ce équivalent à 'new DispatcherFrame (true)'; –

14

Appel PushFrame sur le même répartiteur de threads différents ne fonctionne tout simplement pas de sens, vous ne l'avez pas écrit ce problème que vous essayez de résoudre, mais votre solution PushFrame-est probablement faux. L'objet Dispatcher est responsable de l'exécution du code et de l'événement dispatching pour un thread unique, chaque thread a une file d'attente de messages envoyés par le système d'exploitation et inclut des notifications comme des clics de souris, le dispatcher a une boucle file d'attente et appelle l'événement approprié. Parfois, vous devez traiter des messages sans retourner de votre méthode à la boucle dispatcher, par exemple, des dialogues modaux qui répondent à l'entrée de l'utilisateur (ils doivent donc traiter les messages) sans interrompre le flux de contrôle de la méthode les a appelés.

Ce que fait PushFrame - il exécute la boucle du répartiteur dans votre code. Chaque thread (facultatif) a sa propre file d'attente, les messages sont spécifiques aux fenêtres et aux contrôles qui appartiennent à ce thread, vous ne pouvez pas traiter la file d'attente des messages d'un autre thread (Windows lui-même n'a pas de API qui vous permet de lire les messages d'un autre thread). L'appel de PushFrame à partir d'un autre thread ne peut pas fonctionner car vous êtes appelé sur le mauvais thread, PushFrame lui-même doit être appelé sur le même thread géré par le répartiteur, vous ne pouvez pas l'appeler sur un autre thread car c'est essayer de traiter les messages d'un thread sur un autre thread. Utiliser Invoke ou BeginInvoke n'a pas non plus de sens ici car le délégué passé à ces méthodes n'est appelé que lorsque le répartiteur traite des messages, si le disputeur traite déjà des messages, il n'est pas nécessaire d'appeler PushFrame pour le traiter. .

Si vous posez une autre question décrivant ce que vous essayez de faire, quelqu'un ici peut vous aider, mais appeler Dispatcher.PushFrame à partir de threads différents ne fonctionnera jamais.

+2

Merci, c'est une bonne explication! Le problème est exactement comme vous l'avez décrit. Une boîte de dialogue modale qui est sûre pour les threads. Donc, fondamentalement, comment puis-je utiliser une (1) boîte de dialogue modale unique pour gérer la requête Show() à partir de plusieurs threads? –

+0

Voulez-vous un dialogue modal qui bloquera plusieurs threads jusqu'à ce qu'il se ferme? – Nir

+0

Oui, c'est ce que je cherche. Une boîte de dialogue modale multi-thread. –

Questions connexes