Laden...

Seltsames Verhalten bei Aufruf eines Fensters in externer Assembly

Erstellt von Eco vor 9 Jahren Letzter Beitrag vor 9 Jahren 1.903 Views
E
Eco Themenstarter:in
12 Beiträge seit 2014
vor 9 Jahren
Seltsames Verhalten bei Aufruf eines Fensters in externer Assembly

Hallo zusammen,

folgendes, im Grunde simples Konstrukt ist gegeben:
Eine ausführbare Assembly (A.exe) ruft in einer Assembly (B.dll) eine Methode auf, welche das Hauptfenster der Anwendung erzeugt und darstellt:

Aufruf aus A.exe


AssemblyClass aClass;

aClass = new AssemblyClass();

aClass.ZeigeFenster();    

Methode in B.dll

            
public void ZeigeFenster()
{
    formTest fForm;

    fForm = new formTest();

    System.Windows.Forms.Application.Run(fForm);
}

Nun habe ich das Phänomen, dass nach diesem Aufruf die Anwendung sofort wieder in die ausführbare Assembly A.exe zurückkehrt, diese beendet wird und damit auch das geöffnete Fenster in der Assembly B.dll sofort wieder schließt.

Ergänze ich nun in A.exe weiteren Code nach dem Aufruf von "ZeigeFenster", funktioniert das Ganze.


AssemblyClass aClass;

aClass.ZeigeFenster();    

if (aClass == null)
    return;

Klappt auch:


AssemblyClass aClass;

aClass.ZeigeFenster();    

MessageBox.Show("Test");

Das Fenster wird korrekt dargestellt und in A.exe wird erst weitergemacht, wenn das Fenster durch den Benutzer geschlossen wird (die Meldung wird z.B. erst danach angezeigt).

Der obige Code ist natürlich nur beispielhaft, ich kann leider aufgrund des Umfangs nicht den kompletten Code posten. Mir ist es bisher auch nicht gelungen, das Problem in einer reduzierten Test-Anwendung nachzustellen.

Weiterhin merkwürdig ist, dass das Problem bei der Debug-Ausführung im Visual Studio nicht auftritt, nur beim direkten Ausführen von A.exe.

Hat jemand eine Idee/einen Ansatz, wie ich das Problem angehen kann oder kennt gar den Grund für das Verhalten?

Ich danke im voraus für Eure Antworten!

Gruß
Eco

4.939 Beiträge seit 2008
vor 9 Jahren

Hallo Eco,

m.E. wäre es bessser, wenn nur die Hauptassembly "Application.Run()" aufruft, und deine 2. Assembly lediglich die Form erzeugt, d.h.


AssemblyClass aClass = new AssemblyClass();

Form form = aClass.ErzeugeFenster();

System.Windows.Forms.Application.Run(form);

Gelöschter Account
vor 9 Jahren

Ich hatte so ein ähnliches Scenario auch mal.

Dem Anschein nach gibt es in deiner Anwendung bereits eine bestehende Nachrichtenschleife(registrierte WndProc). Die kann man in .NET bestenfalls so überschreiben das du den Aufruf in einen anderen Thread kapselst und auf das beenden wartest. Im gleichen Thread nochmal Application.Run aufzurufen bringt so ziemlich null komma nix. Irgendwer oder irgendwas in deinem Thread hat bereits eine aktive Nachrichtenschleife.

(Dein Beispielcode ergibt meines Erachtens keinen Sinn bzw. geht von falschen Prämissen aus. Das Problem ist nicht wirklich die folgende Codezeile, auf jeden Fall nicht für if (aClass == null) )

49.485 Beiträge seit 2005
vor 9 Jahren

Hallo Eco,

ich stimme Th69, dass das Application.Run besser im Main (von A) ausgeführt werden sollte.

Wenn allerdings A gar nichts mit dem GUI zu tun hat bzw. zu tun haben soll, dann ginge es auch, wenn Application.Run in ZeigeFenster ausgeführt werden würde. Wenn der Aufruf von ZeigeFenster aus Main (oder allgemeiner gesprochen aus dem Main-Thread) heraus erfolgt, dann funktioniert das. Ich habs zu vollen Sicherheit sogar ausprobiert! Die Methode ZeigeFenster kehrt erst zurück, wenn Application.Run beendet ist, was wiederum normalerweise erst passiert, wenn das Fenster geschlossen wird bzw. explizit Application.Exit aufgerufen wird.

Der Code nach ZeigeFenster wird also erst ausgeführt, wenn Application.Run beendet ist.

Es sei denn in deiner Anwendung sind Thread, BackgroundWorker, Tasks o.ä. im Spiel, die du uns hier verschwiegen hast.

Wenn das nicht der Fall ist und alles scheinbar korrekt ist und es trotzdem nicht funktioniert, siehe [Tutorial] Vertrackte Fehler durch Vergleich von echtem Projekt mit minimalem Testprojekt finden.

Die Verwendung und Wirkung von Application.Run gehört zu den absoluten Grundlagen von Windows Forms. Bitte beachte insofern [Hinweis] Wie poste ich richtig? Punkt 1.1.1.

herbivore

S
145 Beiträge seit 2013
vor 9 Jahren

du musst in ZeigeFenster nicht zwingend Application.Run aufrufen
ein einfaches aufrufen von ShowDialog der form tuts auch.

.Net schaut intern ob schon eine Nachrichtenschleife läuft, wenn nicht wird intern entsprechend eine gestartet.

49.485 Beiträge seit 2005
vor 9 Jahren

Hallo Spyke,(

.Net schaut intern ob schon eine Nachrichtenschleife läuft, wenn nicht wird intern entsprechend eine gestartet.

nein, ShowDialog führt immer seine eigene Nachrichtenschleife aus. Eine (etwaige) umgebende Nachrichtenschleife steht solange die Nachrichtenschleife im ShowDialog läuft.

Wenn ich mich im konkreten Fall zwischen Application.Run (new MyForm ()) und new MyForm().ShowDialog () entscheiden müsste, würde ich Application.Run wählen.

herbivore

E
Eco Themenstarter:in
12 Beiträge seit 2014
vor 9 Jahren

Zur Klarstellung:
A.exe ruft eine Methode mit Oberfläche in B.dll auf, diese Methode wird aber auch in anderen Anwendungen benötigt. Die Methode prüft mittels Application.MessageLoop, ob bereits eine Meldungsschleife existiert, falls ja, wird ShowDialog verwendet, sonst Application.Run.

Die Zeile "if (aClass == null)" war nur ein Beispiel für nachfolgenden Code, natürlich ergibt diese wenig Sinn. Aber dieses Stück Code reicht eben, um das erwartete Verhalten zu erzielen und nicht das seltsame oben beschriebene.

Threading, Tasks o.ä. kommt an dieser Stelle nicht ins Spiel, BackgroundWorker nutze ich prinzipiell nicht.

Aber ich werde beizeiten nochmal eine Beispielanwendung aufbauen und sukzessive Code aus der Echt-Anwendung übernehmen, bis der Fehler reproduzierbar ist. Werde dann berichten.

Danke für Eure Antworten.