Laden...

WPF-GUI in eigener AppDomain Starten

Erstellt von Stu42 vor 7 Jahren Letzter Beitrag vor 7 Jahren 2.276 Views
S
Stu42 Themenstarter:in
506 Beiträge seit 2006
vor 7 Jahren
WPF-GUI in eigener AppDomain Starten

Hi,

das Programm an dem ich gerade arbeite übernimmt u.a. Steuerungsaufgaben von
angeschlossenen Geräten.
Der Steuerungsprozess läuft dabei in einer eigener AppDomain und kommuniziert mit der WPF-GUI
über MemoryMappedFiles.

Sollte die GUI mal abstürzen, möchte ich nicht das der Steuerungsprozess mit untergeht. Idealer weise würde ich gerne die GUI nach einem Absturz mit Parametern neu starten.

Das Problem ist, dass die WPF-Gui in der ersten AppDomain im Hauptthread läuft.
Wenn die GUI dann abstürzt habe ich leider keine "Überwachungs-App Domain" mehr, welcher die GUI neu starten könnte.

Ich möchte also die GUI in einer eigenen AppDomain ausführen.
Nur wenn ich dies mit folgenden Code mache, können die Resourcedateien nicht geladen werden (ArgumentNullException).


 [STAThread]
        [LoaderOptimization(LoaderOptimization.MultiDomainHost)]
        static void Main()
        {
            AppDomain guiDomain = AppDomain.CreateDomain("Gui");

            guiDomain.DoCallBack(() =>
            {
                SplashScreen splashScreen = new SplashScreen("images/splashscreen.png");
                splashScreen.Show(true);

                App app = new App();
                app.InitializeComponent();
                app.Run();
            });

            /* Der folgende Code wuerde funktionieren
            SplashScreen splashScreen = new SplashScreen("images/splashscreen.png");
            splashScreen.Show(true);

            App app = new App();
            app.InitializeComponent();
            app.Run();*/
        }

Wenn ich den Startup-Code nicht in einer extra Domain ausführe läuft alles.
In dem Domain-Callback kann der SplashScreen bereits nicht auf "images/splashscreen.png"
zugreifen.

Kann es sein, dass am Start Resourcen in den Haupt-AppDomain geladen werden, welche
in einer neuen AppDomain nicht verfügbar sind?

Grüße,
Stu42

709 Beiträge seit 2008
vor 7 Jahren

Hi Stu,
klappt es, wenn du den Uri nach dem Schema pack://application:,,,/DeinAssemblyName;component/images/splashscreen.png (wie hier beschrieben) angibst?

Gruß
Micha

S
Stu42 Themenstarter:in
506 Beiträge seit 2006
vor 7 Jahren

Klappt bei diesem Aufruf leider nicht.

Wenn ich den SplashScreen herausnehme,
bekomme im Haupt ResourceDictionary eine Fehlermeldung, wenn ich ein ResourceDictionary einbinde:


...
 <ResourceDictionary.MergedDictionaries>
        <ResourceDictionary Source="pack://application:,,,/Themes/GenericResources/GenericResources.xaml" />

Exception:

Fehlermeldung:
{"Assembly.GetEntryAssembly() gibt NULL zurück. Legen Sie die Application.ResourceAssembly-Eigenschaft fest, oder verwenden Sie die Syntax &quot;pack://application:,,,/assemblyname;component/&quot;, um die Assembly anzugeben, aus der die Ressource geladen werden soll."}

Wenn ich dann aber den Source-Pfad wie von dir beschrieben abändere, geht es!
Aber beim SplashScreen funktioniert das nicht.

Wahrscheinlich gibt Assembly.GetEntryAssembly() nun mal Null zurück.

Wenn ich den SplashScreen Aufruf aber wie folgt abändere tut es:

SplashScreen splashScreen = new SplashScreen(System.Reflection.Assembly.GetCallingAssembly(), "images/splashscreen.png");

Danke für den Tipp!

Ich hoffe ich mir fliegt diese AppDomain -Umstellung nicht bei viele weiteren Stellen um die Ohren.

5.658 Beiträge seit 2006
vor 7 Jahren

Hi Stu42,

bei deinen Anforderungen würde ich empfehlen, einen Windows-Service und eine separate WPF-Anwendung erstellen. Der Service läuft im Hintergrund und übernimmt die Kommunikation mit den Geräten. Und die Anwendung ermöglicht die Interaktion mit dem Benutzer. Dann kann der Service überprüfen, ob die Anwendung läuft und diese ggf. neu starten.

Andererseits: Wenn die Kommunikation mit den Geräten nur benötigt wird, solange die Anwendung geöffnet ist, erscheinen mir beide Lösungen unnötig kompliziert. Da würde ich die Entwicklungszeit lieber in die Entwicklung von Unit-Tests investieren. Statt also davon auszugehen, daß die Anwendung sowieso ständig abstürzt, und dann dafür einen Workaround zu suchen, würde ich lieber gewährleisten, daß die Anwendung zuverlässig funktioniert und (bei tatsächlichen Fehlern) leicht wartbar ist.

Weeks of programming can save you hours of planning

F
10.010 Beiträge seit 2004
vor 7 Jahren

+1
Zusätzlich haben wir bei Hochverfügbarkeitsanwendungen und Continuous Delivery 2 ( zwei ) Dienste.
Der 2. ist dann als Watchdog und zum Updaten gedacht.
Und beide stellen ( derzeit ) per NancyFx und Amanda einen https Webservice bereit.

S
Stu42 Themenstarter:in
506 Beiträge seit 2006
vor 7 Jahren

Danke für eure Anregungen.

Der Kommunikationsteil wird vorest nur benutzt wenn die GUI lebt.
Ich schaue mal wie schnell ich mit den AppDomainen weiter komme, aber bisher sieht es nur noch einer kleinen Umstellung aus.