So öffnen Sie ein Formular in einem Thread und zwingen es, offen zu bleiben

8

Ich habe immer noch Probleme damit herauszufinden, wie man Winforms in einem separaten UI-Thread erstellt, den ich diskutiert habe. hier .

Beim Versuch, das herauszufinden, habe ich das folgende einfache Testprogramm geschrieben. Ich möchte einfach ein Formular in einem separaten Thread mit dem Namen "UI-Thread" öffnen und den Thread so lange laufen lassen, wie das Formular geöffnet ist, während dem Benutzer erlaubt wird, mit dem Formular zu interagieren (das Drehen ist Cheaten). Ich verstehe, warum das Folgende fehlschlägt und der Thread schließt sofort, aber ich bin mir nicht sicher, was ich tun sollte, um es zu beheben.

%Vor%     
George Mauer 03.10.2008, 15:07
quelle

6 Antworten

13

Rufen Sie in einem neuen Thread Application.Run auf, indem Sie das Formularobjekt übergeben, damit der Thread seine eigene Nachrichtenschleife ausführt, während das Fenster geöffnet ist.

Dann können Sie .Join bei diesem Thread aufrufen, damit Ihr Haupt-Thread wartet, bis der UI-Thread beendet ist, oder einen ähnlichen Trick verwenden, um auf den Abschluss dieses Threads zu warten.

Beispiel:

%Vor%     
Lasse Vågsæther Karlsen 03.10.2008, 15:17
quelle
3

Ich denke, Ihr Problem ist bei diesem Gedanken: "Öffnen Sie ein Formular in einem separaten Thread mit dem Namen 'UI-Thread'"

Der Weg, wie Windows funktioniert, ist so (bitte beachten Sie, dass Vista einige dieser Realitäten ändern kann):

Es gibt einen wichtigen Thread, der als " Hauptthread " oder " UI-Thread " bezeichnet wird. Dieser Thread ist derjenige, der Windows-Nachrichten verarbeitet, wie "hey die Maus klickte auf dieses Pixel. "

Diese Nachrichten werden in eine Warteschlange eingereiht und der Hauptthread verarbeitet sie , wenn sie nicht gerade mit etwas anderem beschäftigt ist .

Wenn Sie also einen Funktionsaufruf foo () für den Hauptthread ausführen, werden lange Zeit keine Windows-Nachrichten verarbeitet, sodass keine Benutzerinteraktion auftreten kann.

Der Haupt-Thread malt auch die Benutzeroberfläche auf dem Bildschirm, sodass lang laufende foo () auch das Malen Ihrer App stoppt.

Alle anderen Threads neben diesem heiligen und speziellen Haupt-Thread sind Grunt-Worker-Threads. Diese Worker-Threads können Dinge tun, aber sie können niemals direkt mit der Benutzeroberfläche interagieren.

Diese Realität verursacht zwei Probleme:

  1. AUSSERHALB DES HAUPTGEWINNS: Da Sie nicht möchten, dass foo () lange läuft, um alle Benutzerinteraktionen zu stoppen, müssen Sie diese Arbeit an einen Worker-Thread senden.

  2. ZURÜCK ZUM HAUPTSTREIFEN: Wenn foo () langlaufend ausgeführt wird, möchten Sie den Benutzer wahrscheinlich über eine Aktion auf der Benutzeroberfläche benachrichtigen. In einem Arbeitsthread ist dies jedoch nicht möglich "zurück" zum Hauptthread.

Ich glaube also, dass Ihr Problem im obigen Programm sehr allgemein ist: Ihr Ziel ist inkorrekt, weil es nicht möglich sein soll, _form.Show () in irgendeinem Thread außer dem heiligen Hauptthread aufzurufen.

    
rice 03.10.2008 15:28
quelle
3
%Vor%     
CheeZe5 03.10.2008 15:23
quelle
2

Sie können ein GUI-Formular in keinem Thread öffnen, da es eine Nachrichtenübermittlung fehlt. Sie müssen eine Nachricht explizit in diesem Thread pumpen, indem Sie Application.Run () in einer Thread-Methode aufrufen. Eine andere Option ist das Aufrufen einer DoEvents () in einer Schleife, wenn Sie etwas anderes tun müssen, da nach dem Application.Run () dieser Thread einen Benutzer darauf wartet, ein Formular an diesem Ausführungspunkt zu schließen.

    
Nenad Dobrilovic 03.10.2008 15:19
quelle
1

Ich denke, ShowDialog statt Show aufzurufen, wird helfen. Das Problem scheint zu sein, dass der Thread kurz nach dem Aufruf von Show beendet wird, danach wird der GET-Wert des Formulars gesammelt. ShowDialog hält den Thread an, führt aber weiterhin form-events aus, sodass der Thread weiterläuft, bis das Formular geschlossen wird.

Normalerweise würde ich es andersherum machen. Führen Sie das Formular für den Startthread aus und starten Sie Hintergrundthreads, wenn Sie lange laufende Hintergrundaufgaben starten möchten.

Ich habe auch Ihre andere Frage gelesen, konnte aber nicht herausfinden, was Sie vorhaben. Bei der MVP-Architektur müssen Sie Ihre Geschäftslogik nicht auf verschiedenen Threads ausführen. Multi Threading ist schwer zu machen, also würde ich nur mehrere Threads verwenden, wenn ich sie wirklich brauche.

    
Mendelt 03.10.2008 15:32
quelle
0

Statt show () auf dem Formular aufzurufen, das auf dem Formular ausgeführt wird, und dann einfach am Ende der Thread-Ausführung innerhalb der Funktion StartUiThread () zu schließen, können Sie den Thread sperren, bis das Formular innerhalb der Methode wie Sie gestoppt wird sperren einfach den anderen Thread. Ex:

%Vor%

Dies bewirkt, dass der neue Thread wartet, bis das Dialogfeld geschlossen wird. Ich weiß nicht, ob das deine Probleme lösen wird, aber es hat meine gelöst.

    
Oli4 01.12.2015 10:28
quelle

Tags und Links