Ich bekomme immer die Fehlermeldung "Der aufrufende Thread kann nicht auf dieses Objekt zugreifen, weil ein anderer Thread es besitzt." online "itw.show ();" wenn diese Funktion zweimal aufgerufen wird. Es funktioniert gut für den ersten Anruf, und nachdem das Fenster geschlossen ist und versucht, erneut zu öffnen, schlägt es fehl. Da ich die Methode "Invoke" auskommentiert habe, funktioniert sie auch nicht mit dem Dispatcher. Bitte helfen Sie mir, die Lösung zu finden. Danke.
----------------- Bearbeiten
Der Grund, warum ich einen neuen Thread erstelle, ist, dass es ein Excel-Add-In ist. Ich kann Fenster vom Hauptthread nicht erstellen, der das Excel ist, das mit Fenstern kollidiert, wenn ich sie vom Hauptthread erstelle.
Was ich nicht verstehe ist, warum die neue Instanz (ItemWindow) aus dem neuen Thread mit dem alten Thread kollidiert.
Ich habe eine einfache Testmethode in einer neuen Anwendung erstellt, die aufgerufen wird, wenn ich auf die Schaltfläche (nur) in meinem Hauptformular klicke. Die Methode sieht folgendermaßen aus:
%Vor% Window1
ist eine Fensterklasse, die ich erstellt habe und die nur eine einzige TextBlock
enthält. Ich kann so oft auf diese Schaltfläche klicken, und es öffnet weiterhin neue Fenster ohne Probleme (unabhängig davon, ob ich die vorherige zuerst schließe).
Ich vermute, dass das Problem in Code auftritt, den Sie uns nicht zeigen. Sie müssen sehr vorsichtig sein, dass nichts in Ihrem neuen Thread versucht, auf irgendeine Benutzeroberfläche zuzugreifen, die sich auf Ihren Hauptthread bezieht. Windows, die auf separaten Threads ausgeführt werden, können nicht miteinander kommunizieren, es sei denn, sie durchlaufen den Dispatcher des anderen Threads. Die Ausnahme, die Sie sehen, wird ausgelöst, wenn auf eine Methode oder Eigenschaft eines DispatcherObject von einem anderen Thread als dem, der das Objekt erstellt hat, zugegriffen wird.
Warum ist es wichtig, dass das neue Fenster einen eigenen Thread hat? Wenn das neue Fenster den Thread nicht monopolisiert, wird es wahrscheinlich auf dem Hauptthread gut laufen. Wenn Sie eine lange blockierende Operation ausführen, sollte diese Operation möglicherweise nur in einen Thread und nicht in das gesamte Fenster verschoben werden. Ich weiß nicht, was Sie genau machen, aber es ist etwas, worüber Sie nachdenken können.
BEARBEITEN: Da Sie feststellen, dass Sie möglicherweise nicht in einer typischen WPF-Anwendung ausgeführt werden (sieht so aus, als ob Sie in einem Office-Plugin wären), habe ich meinen Test aktualisiert, um die Fenster vollständig eigenständig auf ihren eigenen Threads zu starten. Ich bin jedoch immer noch in der Lage, zwei Fenster hintereinander ohne Probleme zu starten.
Hier ist mein neuer Test. Diese Methode und die Testklasse Window1
sind die Gesamtheit meiner Anwendung.
Es scheint also an sich nichts falsch zu sein mit dem, was Sie zu tun versuchen, noch sehe ich irgendein offensichtliches Problem in Ihrem Code. Ich vermute, dass irgendwo in Ihrem benutzerdefinierten Fenster eine ungültige Cross-Thread-Kommunikation stattfindet, während sie angezeigt wird. (Entweder das, oder Sie stoßen auf ein Problem speziell für Office-Plugins.)
Eine mögliche Ursache sind Abhängigkeitseigenschaften. Abhängigkeitseigenschaften sind ein wenig wählerisch, wenn es um das Threading geht.
Auch wenn Sie keine eigenen DepProps definieren, wird Ihr Fenster immer noch einige haben und es gibt keine Möglichkeit, sie loszuwerden.
DepProps haben einen erheblichen Nachteil: Sie sind Thread-gebunden und können nicht von einem anderen Thread aus aufgerufen werden. Welcher Thread alle Rechte besitzt, wird durch den Thread definiert, der die DepProps initialisiert, in Ihrem Fall der erste Aufruf von new ItemWindow()
. Nach diesem ersten Aufruf wird Ihr Thread festgelegt und Sie benötigen diesen Thread, um auf Ihre DepProps zuzugreifen.
Für das erste Fenster ist das kein Problem, aber das zweite hatte eindeutig einen anderen Thread. Ich weiß nicht genau, wie DepProps das tut, aber Sie könnten versuchen, den Synchronisationskontext des ersten Threads zu erfassen und wiederherzustellen. Eine andere Möglichkeit wäre, den Dispatcher des ersten Threads (nicht den Hauptthread) zu erfassen
Tags und Links wpf c# multithreading excel-addins