.NET Core中没有AppDomains!为什么?

Adi*_*thi 72 .net clr appdomain .net-core

微软是否有理由选择不支持.NET Core中的AppDomains?

AppDomains在构建长时间运行的服务器应用程序时特别有用,我们可能希望更新服务器加载的程序集是一种优雅的方式,而无需关闭服务器.

如果没有AppDomains,我们如何在长时间运行的服务器进程中替换我们的程序集?

AppDomains还为我们提供了一种隔离服务器代码不同部分的方法.比如,自定义websocket服务器可以在主appdomain中具有套接字代码,而我们的服务在辅助appdomain中运行.

如果没有AppDomains,则无法使用上述方案.

我可以看到一个论点,可能会讨论使用VM的云概念来处理程序集更改而不必承担AppDomains的开销.但这是微软的想法或说法吗?或者他们有针对上述情况的具体原因和替代方案?

Han*_*ant 44

.NETCore子集的要点是保持.NET安装的.并且易于移植.这就是为什么你可以在Windows和OSX上运行Silverlight应用程序,而不是在访问网页时等待很长时间.下载和安装完整的运行时和框架需要花费一些时间,给予或接受.

保持小巧不可避免地需要削减功能.Remoting在这个名单上非常高,它非常昂贵.否则很好地隐藏,但您可以看到委托不再具有功能的BeginInvoke()方法.这也将AppDomain放在剪切列表中,如果没有远程支持,则无法在app域中运行代码.所以这完全是设计的.

  • 程序员倾向于认为.NETCore是新的.微软几乎没有消除这个概念,至少没有将5.0版本号更改为1.0.CoreCLR已经存在了很长一段时间,它开始作为.NET Compact的运行时.Silverlight和WinRT/UWP运行时在它们开源之前是它的显着用途.之前已经移植到OSX和各种WinCE移动处理器的最佳运行时版本. (8认同)
  • 恕我直言,它与大小无关,但事实上CoreCLR没有强大的命名,因此有一个新的融合系统和一种新的方式来查看一个程序集是什么,它的身份和它被加载到的位置,意味着appdomain作为容器不再有用. (7认同)
  • 即使您没有使用强命名,AppDomains也可以在完整的.NET中使用.(例如,AppDomains提供故障隔离的能力并不依赖于强大的命名.)因此,删除强命名本身并不是删除AppDomains的理由. (6认同)
  • 嗯,不.保持下载大小为6.6 MB当然需要删除多个功能. (5认同)
  • 我糊涂了..Net Core和Silverlight之间有什么关系? (3认同)

Jer*_*oen 38

.NET Standard 2和.NET Core 2的更新

在.NET Standard 2中,AppDomain在那里.但是,该API的许多部分都将引发PlatformNotSupportedException.NET Core.

它仍然在那里的主要原因是对于像注册一个未处理的异常处理这些基本的东西工作.

.NET标准常见问题解答有这样的解释:

AppDomain是.NET Standard的一部分吗?

AppDomain类型是.NET Standard的一部分.并非所有平台都支持创建新的应用程序域,例如,.NET Core不会,因此在.NET Standard中可用的方法AppDomain.CreateDomain可能会抛出PlatformNotSupportedException.

我们在.NET Standard中公开此类型的主要原因是因为使用率相当高并且通常与创建新的应用程序域无关,而是与当前应用程序域进行交互,例如注册未处理的异常处理程序或要求应用程序的基本目录.

除此之外,最佳答案和其他答案也很好地解释了为什么大部分AppDomain仍被切断(例如抛出一个不支持的异常).

  • 抛出“平台不支持”异常的跨平台 API 不是跨平台 API。 (4认同)

cwi*_*hva 15

应用程序域

为什么停产?AppDomains需要运行时支持,并且通常非常昂贵.虽然仍由CoreCLR实现,但它在.NET Native中不可用,我们不打算在那里添加此功能.

我应该用什么呢?AppDomains用于不同目的.对于代码隔离,我们建议使用进程和/或容器.对于动态加载程序集,我们建议使用新的AssemblyLoadContext类.

来自MSDN博客


bri*_*lam 8

有一次,我听说将在不使用域的情况下启用卸载程序集.我认为System.Runtime.Loader.AssemblyLoadContextSystem.Runtime.Loader.dll 中的类型与此工作有关,但我没有看到任何启用卸载的内容.


Ste*_*ger 8

您不再需要 AppDomains,您现在拥有 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"
Run Code Online (Sandbox Code Playgroud)

然后你可以说

eval.LoadContext.Unload();
eval.Stream.Dispose();
Run Code Online (Sandbox Code Playgroud)

如果你把它放到抽象类的 IDisposable 接口中,那么你可以使用 using,如果你愿意的话。

注意:
这假设在公共程序集中有一个固定的抽象类

public abstract class MyAbstractClass 
{

     public virtual void foo()
     {}
}
Run Code Online (Sandbox Code Playgroud)

和动态运行时生成的类(使用 Roslyn),引用公共程序集中的抽象类,它实现例如:

public class RsEval: MyAbstractClass 
{

     public override void foo()
     {}
}
Run Code Online (Sandbox Code Playgroud)


Tho*_*mas 5

我在社区站会或微软的一些讨论中听说 AppDomains 的隔离功能更好地由进程处理(实际上是其他平台中的常见模式),并且卸载确实被计划为与 AppDomains 无关的正常功能。