117

Is there a strong reason why Microsoft chose not to support AppDomains in .NET Core?

AppDomains are particularly useful when building long running server apps, where we may want to update the assemblies loaded by the server is a graceful manner, without shutting down the server.

Without AppDomains, how are we going to replace our assemblies in a long running server process?

AppDomains also provide us a way to isolate different parts of server code. Like, a custom websocket server can have socket code in primary appdomain, while our services run in secondary appdomain.

Without AppDomains, the above scenario is not possible.

I can see an argument that may talk about using VMs concept of Cloud for handling assembly changes and not having to incur the overhead of AppDomains. But is this what Microsoft thinks or says? or they have a specific reason and alternatives for the above scenarios?

ympostor
  • 909
  • 7
  • 16
Aditya Pasumarthi
  • 1,219
  • 2
  • 9
  • 3
  • 11
    But .NET Core 5 **is not** .NET Framework. It's not _upcoming version of .NET CLR 4.6_ but another separate thing then don't worry, AppDomain is here to stay. – Adriano Repetti Dec 03 '14 at 08:34
  • 2
    I see that, but if Microsoft is claiming that .NET Core 5 is going to be multi platform (Windows/Linux/Unix), then I'm curious about why they want to remove a core feature like AppDomain. – Aditya Pasumarthi Dec 03 '14 at 08:37
  • 3
    I guess (but it's just my opinion) they're harder to implement in a multi-platform manner, they slow down many things and add complexity. Not so many people uses them (at least most people doesn't do it directly). If you don't need them you may use .NET Core. If you need them...don't use it (think ReFS vs NTFS). Simply .NET Core isn't .NET future (so far) but a separate project. Maybe a workbench but for sure not a migration path or 1:1 alternative (at least now). – Adriano Repetti Dec 03 '14 at 08:58
  • @AdrianoRepetti: Consider adding this as an answer, since I think it is useful as such. – Patrick Hofman Dec 03 '14 at 09:00
  • @PatrickHofman it's just my opinion (2nd comment), I could answer as community wiki but I leave this _duty_ to someone with a more fluent English! – Adriano Repetti Dec 03 '14 at 09:10
  • @AdrianoRepetti: Okay. Thanks for your thoughts though. – Patrick Hofman Dec 03 '14 at 09:11
  • .NET Core has a new concept of "load context" (or something akin), that is `IDisposable`. It allows you to unload assemblies that way, without the enforced boundaries you get from app domains. – Alxandr Dec 03 '14 at 10:41
  • @Alxandr I'm interested in knowing more about "load context". Can you please elaborate, if you have more info? Probably this has some answers to my question. – Aditya Pasumarthi Dec 05 '14 at 11:11
  • Because Microservices architecture with Containerization changed the whole paradigm.. so net core is inclined towards that. Technology and platform independent but container dependent. For such implementation from Microsoft side, at first you would need a smaller codebase/CLR for a quick start and for multiple containers.. – hB0 Jun 29 '20 at 12:06

6 Answers6

55

The point of the .NETCore subset was to keep a .NET install small. And easy to port. Which is why you can, say, run a Silverlight app on both Windows and OSX and not wait very long when you visit the web page. Downloading and installing the complete runtime and framework takes a handful of seconds, give or take.

Keeping it small inevitably requires features to be cut. Remoting was very high on that list, it is quite expensive. Otherwise well hidden, but you can for example see that delegates no longer have a functional BeginInvoke() method. Which put AppDomain on the cut list as well, you can't run code in an app domain without remoting support. So this is entirely by design.

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 14
    IMHO it has nothing to do with size, but with the fact that CoreCLR doesn't have strong naming, and thus has a new fusion system and a new way of looking at what an assembly is, its identity and where it is loaded into, meaning appdomain as a container is no longer useful. – Frans Bouma Dec 03 '14 at 12:06
  • 8
    Hmm, no. Keeping the download size to 6.6 MB did of course require removing more than one feature. – Hans Passant Dec 03 '14 at 14:49
  • 9
    AppDomains can be useful in full .NET even if you're not using strong naming. (E.g., AppDomains' ability to provide fault isolation does not depend on strong naming.) So removal of strong naming would not on its own be a reason to remove AppDomains. – Ian Griffiths Feb 27 '15 at 09:03
  • 5
    I'm confused. What is the relation between .Net Core and Silverlight? – svick Jun 02 '16 at 00:44
  • 11
    Programmers tend to assume that .NETCore is new. Microsoft does very little to dispel this notion, not in the least by changing the 5.0 version number to 1.0. CoreCLR has been around a very long time, started life as the runtime for .NET Compact. Silverlight and the WinRT/UWP runtime are notable uses for it before they open-sourced it. Best runtime version to choose, having previously already been ported to OSX and various WinCE mobile processors. – Hans Passant May 29 '17 at 12:56
54

Update for .NET Standard 2 and .NET Core 2

In .NET Standard 2 the AppDomain class is in there. However, many parts of that API will throw a PlatformNotSupportedException for .NET Core.

The main reason it's still in there is for basic stuff like registering an unhandled exception handler which will work.

The .NET Standard FAQ has this explanation:

Is AppDomain part of .NET Standard?

The AppDomain type is part of .NET Standard. Not all platforms will support the creation of new app domains, for example, .NET Core will not, so the method AppDomain.CreateDomain while being available in .NET Standard might throw PlatformNotSupportedException.

The primary reason we expose this type in .NET Standard is because the usage is fairly high and typically not associated with creating new app domains but for interacting with the current app domain, such as registering an unhandled exception handler or asking for the application's base directory.

Apart from that, the other answer and other answers also nicely explain why the bulk of AppDomain was still cut (e.g. throws a not supported exception).

StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Jeroen
  • 60,696
  • 40
  • 206
  • 339
  • 7
    A cross-platform API that throws "platform not supported" exceptions is not a cross-platform API. – Triynko Apr 22 '21 at 17:41
  • True. But if it helps thousands of applications migrate from .NET to .NET Core it _might_ be worth it...? – Jeroen Apr 22 '21 at 17:54
36

App Domains

Why was it discontinued? AppDomains require runtime support and are generally quite expensive. While still implemented by CoreCLR, it’s not available in .NET Native and we don’t plan on adding this capability there.

What should I use instead? AppDomains were used for different purposes. For code isolation, we recommend processes and/or containers. For dynamic loading of assemblies, we recommend the new AssemblyLoadContext class.

Source: Porting to .NET Core | .NET Blog

Pang
  • 9,564
  • 146
  • 81
  • 122
cwishva
  • 1,940
  • 1
  • 18
  • 23
  • 1
    One question, what do you mean by `For code isolation, we recommend processes and/or containers`... Is there a container api available in .net core? – Ivandro Jao Jul 13 '19 at 16:09
  • @IvandroIsmael , they mean "split your single app/module into separate interacting apps/modules/processes/containers" (most probably - into microservices), i.e. refactor your app not to use AppDomains for code isolation – Burst Nov 26 '19 at 13:06
24

You don't need AppDomains anymore, you now have 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"

and then you can say

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

Bonus if you put that into the IDisposable interface of the abstract class, then you can just use using, if you want to.

Note:
This assumes a fixed abstract class in a common assembly

public abstract class MyAbstractClass 
{

     public virtual void foo()
     {}
}

and a dynamically runtime-generated class ( using Roslyn), referencing the abstract class in the common assembly, which implements e.g.:

public class RsEval: MyAbstractClass 
{

     public override void foo()
     {}
}
Stefan Steiger
  • 78,642
  • 66
  • 377
  • 442
11

At one point, I heard that unloading assemblies would be enabled without using domains. I think that the System.Runtime.Loader.AssemblyLoadContext type in System.Runtime.Loader.dll is related to this work, but I don't see anything there that enables unloading yet.

bricelam
  • 28,825
  • 9
  • 92
  • 117
5

I have heard in a community standup or some talk of Microsoft that the isolation feature of AppDomains are better handled by processes (and actually the common pattern in other platforms) and the unloading is indeed planned as a normal feature unrelated to AppDomains.

Thomas
  • 5,080
  • 27
  • 42