Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
WPF-GUI in eigener AppDomain Starten
Stu42
myCSharp.de - Member



Dabei seit:
Beiträge: 506
Herkunft: Aus dem Norden

Themenstarter:

WPF-GUI in eigener AppDomain Starten

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
pinki
myCSharp.de - Member

Avatar #avatar-4072.jpg


Dabei seit:
Beiträge: 704
Herkunft: OWL

beantworten | zitieren | melden

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

Gruß
Micha
private Nachricht | Beiträge des Benutzers
Stu42
myCSharp.de - Member



Dabei seit:
Beiträge: 506
Herkunft: Aus dem Norden

Themenstarter:

beantworten | zitieren | melden

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:
Fehler
{"Assembly.GetEntryAssembly() gibt NULL zurück. Legen Sie die Application.ResourceAssembly-Eigenschaft fest, oder verwenden Sie die Syntax \"pack://application:,,,/assemblyname;component/\", 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.
private Nachricht | Beiträge des Benutzers
MrSparkle
myCSharp.de - Team

Avatar #avatar-2159.gif


Dabei seit:
Beiträge: 5988
Herkunft: Leipzig

beantworten | zitieren | melden

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
private Nachricht | Beiträge des Benutzers
FZelle
myCSharp.de - Experte



Dabei seit:
Beiträge: 10083

beantworten | zitieren | melden

+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.
private Nachricht | Beiträge des Benutzers
Stu42
myCSharp.de - Member



Dabei seit:
Beiträge: 506
Herkunft: Aus dem Norden

Themenstarter:

beantworten | zitieren | melden

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.
private Nachricht | Beiträge des Benutzers