Keine AppDomains in .NET Core! Warum?

87

Gibt es einen starken Grund, warum Microsoft AppDomains in .NET Core nicht unterstützt?

AppDomains sind besonders nützlich, wenn Sie Server-Apps mit langer Laufzeit erstellen, bei denen wir die vom Server geladenen Assemblys auf anmutige Weise aktualisieren möchten, ohne den Server herunterzufahren.

Wie können wir ohne AppDomains unsere Assemblys in einem lang laufenden Serverprozess ersetzen?

AppDomains bieten uns auch die Möglichkeit, verschiedene Teile des Servercodes zu isolieren. Ein benutzerdefinierter Websocket-Server kann Socket-Code in der primären App-Domäne haben, während unsere Dienste in der sekundären App-Domäne ausgeführt werden.

Ohne AppDomains ist das obige Szenario nicht möglich.

Ich sehe ein Argument, das möglicherweise über die Verwendung des Cloud-Konzepts von VMs zur Behandlung von Baugruppenänderungen spricht und nicht den Aufwand für AppDomains verursachen muss. Aber denkt oder sagt Microsoft das? oder haben sie einen bestimmten Grund und Alternativen für die oben genannten Szenarien?

Aditya Pasumarthi
quelle
9
.NET Core 5 ist jedoch nicht .NET Framework. Es ist keine kommende Version von .NET CLR 4.6, aber eine andere Sache, dann keine Sorge, AppDomain ist hier, um zu bleiben.
Adriano Repetti
2
Ich sehe das, aber wenn Microsoft behauptet, dass .NET Core 5 plattformübergreifend sein wird (Windows / Linux / Unix), bin ich gespannt, warum sie eine Kernfunktion wie AppDomain entfernen möchten.
Aditya Pasumarthi
3
Ich denke (aber es ist nur meine Meinung), dass es schwieriger ist, sie plattformübergreifend zu implementieren, sie verlangsamen viele Dinge und erhöhen die Komplexität. Nicht so viele Leute benutzen sie (zumindest machen es die meisten Leute nicht direkt). Wenn Sie sie nicht benötigen, können Sie .NET Core verwenden. Wenn Sie sie brauchen ... verwenden Sie sie nicht (denken Sie an ReFS vs NTFS). Einfach .NET Core ist (bisher) keine .NET-Zukunft, sondern ein separates Projekt. Vielleicht eine Workbench, aber sicher kein Migrationspfad oder eine 1: 1-Alternative (zumindest jetzt).
Adriano Repetti
@AdrianoRepetti: Erwägen Sie, dies als Antwort hinzuzufügen, da ich denke, dass es als solches nützlich ist.
Patrick Hofman
@PatrickHofman es ist nur meine Meinung (2. Kommentar), ich könnte als Community-Wiki antworten, aber ich überlasse diese Pflicht jemandem mit einem fließenderen Englisch!
Adriano Repetti

Antworten:

50

Der Zweck der .NETCore-Teilmenge bestand darin, eine .NET-Installation klein zu halten . Und einfach zu portieren. Aus diesem Grund können Sie beispielsweise eine Silverlight-App unter Windows und OSX ausführen und nicht lange warten, wenn Sie die Webseite besuchen. Das Herunterladen und Installieren der gesamten Laufzeit und des Frameworks dauert einige Sekunden.

Um es klein zu halten, müssen zwangsläufig Merkmale geschnitten werden. Remoting stand ganz oben auf dieser Liste, es ist ziemlich teuer. Ansonsten gut versteckt, aber Sie können zum Beispiel sehen, dass Delegaten keine funktionierende BeginInvoke () -Methode mehr haben. Damit AppDomain ebenfalls auf die Schnittliste gesetzt wird, können Sie keinen Code in einer App-Domäne ausführen, ohne Unterstützung für Remoting zu erhalten. Das ist also völlig beabsichtigt.

Hans Passant
quelle
12
IMHO hat es nichts mit Größe zu tun, sondern mit der Tatsache, dass CoreCLR keine starke Benennung hat und somit ein neues Fusionssystem und eine neue Sichtweise auf das, was eine Baugruppe ist, ihre Identität und wo sie geladen wird, hat. Appdomain als Container ist also nicht mehr sinnvoll.
Frans Bouma
7
Hmm, nein. Um die Downloadgröße auf 6,6 MB zu halten, mussten natürlich mehr als eine Funktion entfernt werden.
Hans Passant
7
AppDomains können in Full .NET nützlich sein, auch wenn Sie keine starken Namen verwenden. (Zum Beispiel hängt die Fähigkeit von AppDomains, eine Fehlerisolierung bereitzustellen, nicht von einer starken Benennung ab.) Das Entfernen einer starken Benennung allein wäre also kein Grund, AppDomains zu entfernen.
Ian Griffiths
5
Ich bin verwirrt. Welche Beziehung besteht zwischen .Net Core und Silverlight?
Svick
10
Programmierer neigen dazu anzunehmen, dass .NETCore neu ist. Microsoft unternimmt sehr wenig, um diesen Gedanken zu zerstreuen, nicht zuletzt, indem es die 5.0-Versionsnummer auf 1.0 ändert. CoreCLR gibt es schon seit sehr langer Zeit und begann als Laufzeit für .NET Compact. Silverlight und die WinRT / UWP-Laufzeit sind bemerkenswerte Verwendungszwecke, bevor sie als Open-Source-Version verwendet werden. Beste Laufzeitversion zur Auswahl, da sie bereits auf OSX und verschiedene mobile WinCE-Prozessoren portiert wurde.
Hans Passant
46

Update für .NET Standard 2 und .NET Core 2

In .NET Standard 2 die AppDomainKlasse ist da drin. Viele Teile dieser API werfen jedoch einen PlatformNotSupportedExceptionfür .NET Core.

Der Hauptgrund , es ist immer noch da drin ist für grundlegenden Dinge wie ein nicht behandelte Exception - Handler registrieren , die wird funktionieren.

Die .NET Standard-FAQ enthält folgende Erklärung :

Ist AppDomain Teil von .NET Standard?

Der AppDomain-Typ ist Teil von .NET Standard. Nicht alle Plattformen unterstützen die Erstellung neuer App-Domänen, z. B. .NET Core nicht. Daher kann die in .NET Standard verfügbare Methode AppDomain.CreateDomain PlatformNotSupportedException auslösen.

Der Hauptgrund, warum wir diesen Typ in .NET Standard verfügbar machen, ist, dass die Nutzung ziemlich hoch ist und normalerweise nicht mit dem Erstellen neuer App-Domänen verbunden ist, sondern mit der Interaktion mit der aktuellen App-Domäne, z. B. dem Registrieren eines nicht behandelten Ausnahmebehandlers oder dem Abfragen des Basisverzeichnisses der Anwendung .

Abgesehen davon erklären die Top-Antwort und andere Antworten auch gut, warum der Großteil von AppDomain immer noch gekürzt wurde (z. B. löst eine nicht unterstützte Ausnahme aus).

Jeroen
quelle
19

App Domains

Warum wurde es eingestellt? AppDomains benötigen Laufzeitunterstützung und sind im Allgemeinen recht teuer. Obwohl es noch von CoreCLR implementiert ist, ist es in .NET Native nicht verfügbar, und wir planen nicht, diese Funktion dort hinzuzufügen.

Was soll ich stattdessen verwenden? AppDomains wurden für verschiedene Zwecke verwendet. Zur Code-Isolierung empfehlen wir Prozesse und / oder Container. Zum dynamischen Laden von Assemblys empfehlen wir die neue AssemblyLoadContext-Klasse.

Quelle aus dem MSDN-Blog

cwishva
quelle
Eine Frage, was meinst du mit For code isolation, we recommend processes and/or containers... Gibt es eine Container-API im .net-Kern?
Ivandro Jao
@IvandroIsmael, sie bedeuten "Teilen Sie Ihre einzelne App / Modul in separate interagierende Apps / Module / Prozesse / Container" (höchstwahrscheinlich - in Microservices), dh überarbeiten Sie Ihre App, um AppDomains nicht für die Codeisolierung zu verwenden
Burst
10

Irgendwann hörte ich, dass das Entladen von Assemblys ohne Verwendung von Domänen aktiviert werden würde. Ich denke, dass der System.Runtime.Loader.AssemblyLoadContextTyp in System.Runtime.Loader.dll mit dieser Arbeit zusammenhängt, aber ich sehe dort noch nichts, was das Entladen ermöglicht.

Bricelam
quelle
5

Ich habe in einem Community-Standup oder in einem Vortrag von Microsoft gehört, dass die Isolationsfunktion von AppDomains besser von Prozessen (und tatsächlich das übliche Muster auf anderen Plattformen) gehandhabt wird und das Entladen tatsächlich als normale Funktion geplant ist, die nichts mit AppDomains zu tun hat.

Thomas
quelle
1

Sie brauchen keine AppDomains mehr, Sie haben jetzt LoadContexts:

public class CollectibleAssemblyLoadContext 
    : AssemblyLoadContext
{
    public CollectibleAssemblyLoadContext() : base(isCollectible: true)
    { }
 
    protected override Assembly Load(AssemblyName assemblyName)
    {
        return null;
    }
}

byte[] result = null; // Assembly Emit-result from roslyn
System.Runtime.Loader.AssemblyLoadContext context = new CollectibleAssemblyLoadContext();
System.IO.Stream ms = new System.IO.MemoryStream(result);
System.Reflection.Assembly assembly = context.LoadFromStream(ms);


System.Type programType = assembly.GetType("RsEval");
MyAbstractClass eval = (MyAbstractClass )System.Activator.CreateInstance(programType);
eval.LoadContext = context;
eval.Stream = ms;
// do something here with the dynamically created class "eval"

und dann kann man sagen

eval.LoadContext.Unload();
eval.Stream.Dispose();

Bonus, wenn Sie das in die IDisposable-Oberfläche der abstrakten Klasse einfügen, können Sie es einfach verwenden, wenn Sie möchten.

Stefan Steiger
quelle