Ist es möglich, mehrere GUI-Threads auszugliedern?(Das System wird bei Application.Run nicht angehalten)

StackOverflow https://stackoverflow.com/questions/2872

  •  08-06-2019
  •  | 
  •  

Frage

Mein Ziel

Ich hätte gerne einen Hauptverarbeitungsthread (ohne GUI) und könnte GUIs nach Bedarf in ihre eigenen Hintergrundthreads ausgliedern, damit mein Hauptthread ohne GUI weiter funktioniert.Anders ausgedrückt: Ich möchte, dass mein Haupt-Nicht-GUI-Thread der Eigentümer des GUI-Threads ist und nicht umgekehrt.Ich bin mir nicht sicher, ob dies überhaupt mit Windows Forms möglich ist (?)

Hintergrund

Ich habe ein komponentenbasiertes System, in dem ein Controller Assemblys dynamisch lädt und Klassen instanziiert und ausführt, die ein Common implementieren IComponent Schnittstelle mit einer einzigen Methode DoStuff().

Welche Komponenten geladen werden, wird über eine XML-Konfigurationsdatei und durch das Hinzufügen neuer Assemblys mit unterschiedlichen Implementierungen von konfiguriert IComponent.Die Komponenten stellen der Hauptanwendung Hilfsfunktionen bereit.Während das Hauptprogramm seine Arbeit erledigt, z.B.Bei der Steuerung eines Kernkraftwerks führen die Komponenten möglicherweise Versorgungsaufgaben aus (in ihren eigenen Threads), z. B.Bereinigen der Datenbank, Versenden von E-Mails, Drucken lustiger Witze auf dem Drucker, was haben Sie?Ich möchte, dass eine dieser Komponenten eine GUI anzeigen kann, z. B.mit Statusinformationen für die E-Mail-Versandkomponente.

Die Lebensdauer des Gesamtsystems sieht folgendermaßen aus

  1. Die Anwendung beginnt.
  2. Überprüfen Sie die Konfigurationsdatei auf zu ladende Komponenten.Laden Sie sie.
  3. Führen Sie für jede Komponente Folgendes aus: DoStuff() um es zu initialisieren und ihm ein eigenes Leben in ihren eigenen Threads zu ermöglichen.
  4. Erledige weiterhin die Hauptanwendungs-Königsarbeit, für immer.

Ich konnte Punkt 3 noch nicht erfolgreich ausführen, wenn die Komponente eine GUI startet DoStuff().Es bleibt einfach stehen, bis die GUI geschlossen wird.Und erst wenn die GUI geschlossen wird, kommt das Programm zu Punkt 4.

Es wäre großartig, wenn diese Komponenten ihre eigenen Windows Forms-GUIs starten könnten.

Problem

Wenn eine Komponente versucht, eine GUI zu starten DoStuff() (Die genaue Codezeile ist, wenn die Komponente ausgeführt wird Application.Run(theForm)), die Komponente und damit unser System „hängt“ am Application.Run() Zeile, bis die GUI geschlossen wird.Nun, die gerade gestartete GUI funktioniert wie erwartet einwandfrei.

Beispiel für Komponenten.Das eine hat nichts mit der grafischen Benutzeroberfläche zu tun, während das zweite ein niedliches Fenster mit rosa flauschigen Hasen öffnet.

public class MyComponent1: IComponent
{
    public string DoStuff(...) { // write something to the database  }
}

public class MyComponent2: IComponent
{
    public void DoStuff()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form());

        // I want the thread to immediately return after the GUI 
        // is fired up, so that my main thread can continue to work.
    }
}

Ich habe es ohne Erfolg versucht.Selbst wenn ich versuche, die GUI in einem eigenen Thread zu starten, wird die Ausführung angehalten, bis die GUI geschlossen wird.

public void DoStuff()
{
    new Thread(ThreadedInitialize).Start()
}

private void ThreadedInitialize()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.Run(new Form());
}

Ist es möglich, eine GUI auszugliedern und danach zurückzukehren? Application.Run()?

War es hilfreich?

Lösung

Anwendung.Ausführen Die Methode zeigt ein (oder mehrere) Formulare an und initiiert die Standardnachrichtenschleife, die ausgeführt wird, bis alle Formulare geschlossen sind.Sie können eine Rückkehr von dieser Methode nicht erzwingen, es sei denn, Sie schließen alle Ihre Formulare oder erzwingen das Herunterfahren der Anwendung.

Sie können jedoch eine übergeben Anwendungskontext (anstelle eines neuen Form()) zur Application.Run-Methode und ApplicationContext können verwendet werden, um mehrere Formulare gleichzeitig zu starten.Ihre Bewerbung endet erst, wenn alle Bewerbungsformulare geschlossen sind.Siehe hier: http://msdn.microsoft.com/en-us/library/system.windows.forms.application.run.aspx

Außerdem werden alle Formulare, die Sie nicht modal anzeigen, weiterhin neben Ihrem Hauptformular ausgeführt, sodass Sie mehr als ein Fenster haben können, das sich nicht gegenseitig blockiert.Ich glaube, das ist tatsächlich das, was Sie erreichen wollen.

Andere Tipps

Ich bin mir sicher, dass dies möglich ist, wenn man sich nur hart genug anstrengt, aber ich würde vorschlagen, dass es keine gute Idee ist.

„Windows“ (die Sie auf dem Bildschirm sehen) sind stark an Prozesse gekoppelt.Das bedeutet, dass von jedem Prozess, der eine grafische Benutzeroberfläche anzeigt, erwartet wird, dass er über eine Nachrichtenschleife verfügt, die alle Nachrichten verarbeitet, die mit der Erstellung und Verwaltung von Fenstern verbunden sind (z. B. „auf die Schaltfläche geklickt“, „die App geschlossen“, „den Bildschirm neu zeichnen“) ' und so weiter.

Aus diesem Grund wird mehr oder weniger davon ausgegangen, dass eine Nachrichtenschleife für die gesamte Lebensdauer Ihres Prozesses verfügbar sein muss.Windows könnte Ihnen beispielsweise eine „Beenden“-Nachricht senden, und Sie müssen über eine Nachrichtenschleife verfügen, um damit umgehen zu können, auch wenn nichts auf dem Bildschirm angezeigt wird.

Am besten machen Sie es so:

Machen Sie ein gefälschtes Formular, das nie angezeigt wird, welches Ihre "Haupt -App" -Start -Anrufanmeldung ist.Erledigen Sie Ihre Arbeit in einem anderen Thread und lösen Sie Ereignisse im Hauptthread aus, wenn Sie Gui-Sachen erledigen müssen.

Ich bin mir nicht sicher, ob das richtig ist, aber ich erinnere mich, dass ich Fensterformulare aus einer Konsolenanwendung ausgeführt habe, indem ich einfach das Formular neu gemacht und newForm.Show() darauf aufgerufen habe. Wenn Ihre Komponenten das anstelle von Application.Run() verwenden, dann das neue Formular sollte nicht blockieren.

Natürlich ist die Komponente dafür verantwortlich, einen Verweis auf die von ihr erstellten Formulare aufrechtzuerhalten

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top