Hier ist der grundlegende Kern meines Problems:
Problem: Wenn in Klasse 4 das eigene -Ereignis von der Ereignisbehandlungsmethode ausgelöst wird, die das Ereignis der Klasse B erfasst hat, wird das Ereignis ausgelöst. Der abonnierende Handler in der Window-Klasse wird jedoch nie aufgerufen.
Es werden keine Ausnahmen ausgelöst. Wenn ich die sekundäre AppDomain entferne, wird das Ereignis problemlos behandelt.
Weiß jemand, warum das nicht funktioniert? Gibt es eine andere Möglichkeit, dies ohne Rückruf auszuführen?
Ich würde denken, dass das Problem in Schritt 3 statt in Schritt 4 auftreten würde.
Hier ist ein echtes Codebeispiel zur Veranschaulichung des Problems:
%Vor% Bei meinem ersten Versuch, dieses Problem zu lösen, habe ich die Vererbung von Klasse B MarshalByRefObject
entfernt und stattdessen als serialisierbar gekennzeichnet. Das Ergebnis war, dass das Objekt nach Wert gemarshallt wurde und ich gerade eine Kopie von Klasse C erhalten habe, die in der Host-AppDomain ausgeführt wird. Das wollte ich nicht.
Die wirkliche Lösung, die ich gefunden habe, war, dass Klasse B ( DangerousProgram
im Beispiel) auch von MarshalByRefObject
erben sollte, damit der Rückruf auch einen Proxy verwendet strong>, um den Thread wieder in die Standard-AppDomain zu übertragen.
By the way, hier ist ein großartiger Artikel , den ich von Eric Lippert gefunden habe das erklärt Marshal durch ref vs. Marshal nach Wert auf sehr clevere Weise.
Die Magie von .NET-Ereignissen verbirgt die Tatsache, dass, wenn Sie ein Ereignis in einer Instanz von B durch eine Instanz von A abonnieren, A in die App-Domäne von B gesendet wird. Wenn A nicht MarshalByRef ist, wird eine Wertkopie von A gesendet. Jetzt haben Sie zwei separate Instanzen von A, weshalb Sie das unerwartete Verhalten erfahren haben.
Wenn es jemandem schwer fällt zu verstehen, wie dies geschieht, schlage ich die folgende Problemumgehung vor, die es offensichtlich macht, warum sich Ereignisse auf diese Weise verhalten.
Um "Ereignisse" in B (innerhalb der Anwendungsdomäne 2) zu erzeugen und sie in A (innerhalb der Anwendungsdomäne 1) zu behandeln, ohne reale Ereignisse zu verwenden, müssen wir ein zweites Objekt erstellen, das Methodenaufrufe übersetzt viel zu) zu Ereignissen (die sich nicht wie erwartet verhalten). Diese Klasse, nennen wir sie X, wird in Appdomain 1 instanziiert, und ihr Proxy wird in Appdomain 2 gesendet. Hier ist der Code:
%Vor%Der Pseudocode würde etwa so aussehen:
Damit B ein Ereignis in AD1 zurückfeuern kann, muss es nicht nur die Methode, sondern auch eine Instanz haben, um diese Methode zu aktivieren. Aus diesem Grund müssen wir einen Proxy von X in AD2 senden. Das ist auch, warum domainübergreifende Ereignisse erfordern, dass der Ereignishandler über die Domänengrenze verteilt wird! Ein Ereignis ist nur ein fantastischer Wrapper um eine Methodenausführung. Und dazu brauchen Sie nicht nur die Methode, sondern auch die Instanz, um sie auszuführen.
Als Faustregel gilt: Wenn Sie Ereignisse über eine Grenze einer Anwendungsdomäne hinweg behandeln wollen, müssen beide Typen - dasjenige, das das Ereignis und das, das es behandelt - das MarshalByRefObject erweitern.
Tags und Links .net events event-handling appdomain