Nessun AppDominio in .NET Core! Perché?


88

C'è un motivo valido per cui Microsoft ha scelto di non supportare AppDomain in .NET Core?

Gli AppDomain sono particolarmente utili quando si creano app server a esecuzione prolungata, in cui è possibile che si desideri aggiornare gli assembly caricati dal server in modo aggraziato, senza arrestare il server.

Senza AppDomains, come sostituiremo i nostri assembly in un processo server di lunga durata?

AppDomain ci fornisce anche un modo per isolare diverse parti del codice del server. Ad esempio, un server websocket personalizzato può avere codice socket nel dominio app principale, mentre i nostri servizi vengono eseguiti nel dominio app secondario.

Senza AppDomains, lo scenario precedente non è possibile.

Posso vedere un argomento che potrebbe parlare dell'utilizzo del concetto di cloud delle VM per la gestione delle modifiche agli assembly e per non dover sostenere l'overhead di AppDomain. Ma è questo ciò che Microsoft pensa o dice? o hanno una ragione specifica e alternative per gli scenari di cui sopra?


9
Ma .NET Core 5 non è .NET Framework. Non è la versione imminente di .NET CLR 4.6 ma un'altra cosa separata quindi non preoccuparti, AppDomain è qui per restare.
Adriano Repetti

2
Lo vedo, ma se Microsoft afferma che .NET Core 5 sarà multipiattaforma (Windows / Linux / Unix), allora sono curioso di sapere perché vogliono rimuovere una funzionalità principale come AppDomain.
Aditya Pasumarthi

3
Immagino (ma è solo la mia opinione) che siano più difficili da implementare in modo multipiattaforma, rallentano molte cose e aggiungono complessità. Non così tante persone li usano (almeno la maggior parte delle persone non lo fa direttamente). Se non ti servono puoi usare .NET Core. Se ne hai bisogno ... non usarlo (pensa a ReFS vs NTFS). Semplicemente .NET Core non è .NET future (finora) ma un progetto separato. Forse un workbench ma di sicuro non un percorso di migrazione o un'alternativa 1: 1 (almeno ora).
Adriano Repetti

@AdrianoRepetti: considera di aggiungere questo come risposta, poiché penso che sia utile in quanto tale.
Patrick Hofman

@PatrickHofman è solo la mia opinione (2 ° commento), potrei rispondere come wiki della comunità ma lascio questo compito a qualcuno con un inglese più fluente!
Adriano Repetti

Risposte:


49

Lo scopo del sottoinsieme .NETCore era mantenere un'installazione .NET ridotta . E facile da portare. Ecco perché puoi, ad esempio, eseguire un'app Silverlight sia su Windows che su OSX e non aspettare molto a lungo quando visiti la pagina web. Il download e l'installazione dell'intero runtime e del framework richiede una manciata di secondi, più o meno.

Mantenerlo piccolo richiede inevitabilmente che le caratteristiche vengano tagliate. Il remoting era molto in cima a quella lista, è piuttosto costoso. Altrimenti ben nascosto, ma puoi ad esempio vedere che i delegati non hanno più un metodo BeginInvoke () funzionale. Il che mette anche AppDomain nell'elenco di taglio, non è possibile eseguire codice in un dominio dell'app senza il supporto remoto. Quindi questo è interamente in base alla progettazione.


13
IMHO non ha nulla a che fare con le dimensioni, ma con il fatto che CoreCLR non ha una denominazione forte, e quindi ha un nuovo sistema di fusione e un nuovo modo di vedere cos'è un assembly, la sua identità e dove viene caricato, significa che appdomain come contenitore non è più utile.
Frans Bouma

7
Hmm, no. Mantenere la dimensione del download a 6,6 MB ha ovviamente richiesto la rimozione di più di una funzionalità.
Hans Passant

8
AppDomains può essere utile in .NET completo anche se non si utilizzano nomi forti. (Ad esempio, la capacità di AppDomain di fornire l'isolamento dei guasti non dipende da una denominazione forte.) Quindi la rimozione di una denominazione forte non sarebbe di per sé un motivo per rimuovere AppDomain.
Ian Griffiths

5
Non ho capito bene. Qual è la relazione tra .Net Core e Silverlight?
svick

10
I programmatori tendono a presumere che .NETCore sia nuovo. Microsoft fa ben poco per dissipare questa nozione, non da ultimo modificando il numero di versione 5.0 in 1.0. CoreCLR esiste da molto tempo, è nato come runtime per .NET Compact. Silverlight e il runtime WinRT / UWP sono usi notevoli per questo prima di renderlo open source. Migliore versione runtime da scegliere, essendo già stata precedentemente portata su OSX e su vari processori mobili WinCE.
Hans Passant

47

Aggiornamento per .NET Standard 2 e .NET Core 2

In .NET Standard 2 la AppDomainclasse è lì. Tuttavia, molte parti di tale API genereranno un PlatformNotSupportedExceptionper .NET Core.

Il motivo principale è ancora in là è per cose di base come la registrazione di un gestore di eccezione non gestita, che si funzionerà.

Le domande frequenti su .NET Standard hanno questa spiegazione :

AppDomain fa parte di .NET Standard?

Il tipo AppDomain fa parte di .NET Standard. Non tutte le piattaforme supporteranno la creazione di nuovi domini di app, ad esempio .NET Core no, quindi il metodo AppDomain.CreateDomain, pur essendo disponibile in .NET Standard, potrebbe generare PlatformNotSupportedException.

Il motivo principale per cui esponiamo questo tipo in .NET Standard è perché l'utilizzo è piuttosto elevato e in genere non è associato alla creazione di nuovi domini dell'app, ma all'interazione con il dominio dell'app corrente, come la registrazione di un gestore di eccezioni non gestito o la richiesta della directory di base dell'applicazione .

A parte questo, la risposta principale e altre risposte spiegano anche bene perché la maggior parte di AppDomain è stata ancora tagliata (ad esempio, genera un'eccezione non supportata).


21

Domini delle app

Perché è stato interrotto? Gli AppDomain richiedono il supporto del runtime e sono generalmente piuttosto costosi. Sebbene sia ancora implementato da CoreCLR, non è disponibile in .NET Native e non abbiamo intenzione di aggiungere questa funzionalità lì.

Cosa dovrei usare invece? Gli AppDomain sono stati utilizzati per scopi diversi. Per l'isolamento del codice, consigliamo processi e / o contenitori. Per il caricamento dinamico degli assembly, si consiglia la nuova classe AssemblyLoadContext.

Fonte dal blog MSDN


Una domanda, cosa intendi con For code isolation, we recommend processes and/or containers... Esiste un'API contenitore disponibile in .net core?
Ivandro Jao

@ IvandroIsmael, significano "dividi la tua singola app / modulo in app / moduli / processi / contenitori separati interagenti" (molto probabilmente - in microservizi), ovvero refactoring della tua app per non utilizzare AppDomain per l'isolamento del codice
Burst

10

A un certo punto, ho sentito che lo scaricamento degli assembly sarebbe stato abilitato senza utilizzare i domini. Penso che il System.Runtime.Loader.AssemblyLoadContexttipo in System.Runtime.Loader.dll sia correlato a questo lavoro, ma non vedo ancora nulla che consenta lo scaricamento.


6

Non hai più bisogno di AppDomain, ora hai 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"

e poi puoi dire

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

Bonus se lo metti nell'interfaccia IDisposable della classe astratta, puoi semplicemente usare using, se lo desideri.

Nota:
questo presuppone una classe astratta fissa in un assembly comune

public abstract class MyAbstractClass 
{

     public virtual void foo()
     {}
}

e una classe generata dinamicamente dal runtime (utilizzando Roslyn), che fa riferimento alla classe astratta nell'assembly comune, che implementa ad esempio:

public class RsEval: MyAbstractClass 
{

     public override void foo()
     {}
}

5

Ho sentito in uno stand-up della comunità o in alcuni discorsi di Microsoft che la funzionalità di isolamento di AppDomain è gestita meglio dai processi (e in realtà lo schema comune in altre piattaforme) e lo scarico è effettivamente pianificato come una normale funzionalità non correlata ad AppDomain.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.