当您将从 MarshalByRefObject 继承的对象传递给不同的 AppDomain 时,创建该对象的 AppDomain 引发的 GC.Collect() 不会收集该对象,前提是该对象在 GC.Collect( 时未植根于任一 AppDomain 中) )叫?
[当我说没有 root 时,我的意思是开发人员编写的代码不再访问它。]
看来该对象并没有被收集,而是被提升到了下一代!
但是,如果我停止将对象传递给 diff AppDomain,它就会按预期被收集。
这是设计使然吗?如果有的话有什么道理吗?
多谢你们,
PS 我知道代码中的 GC.Collect() 出于多种原因是不好的,我只是想了解 GC 如何在 MBRO 上发生。
我主要通过谷歌阅读了很多东西(不是在这里),但没有找到可以回答我的问题的东西,所以我在这里问。
我确实想添加到“某些东西”(AppDomain我认为),以便我的代码可以在运行时解析如何Assembly.CreateInstance访问我的应用程序编译文件夹之外的特定 DLL。
我真的觉得AppDomain是要使用的类,AppendPrivatePath听起来像要使用的方法,但它现在“已过时”... msdn 建议使用 PrivateBinPath 但据我所知,我必须创建一个新的 AppDomain 并通过我的测试,我感觉Assembly.CreateInstance不在我的新 AppDomain 中寻找引用
一些代码如:
AppDomainSetup domaininfo = new AppDomainSetup();
domaininfo.ApplicationBase = AppDomain.CurrentDomain.BaseDirectory;
domaininfo.PrivateBinPath = "D:\\.....\\bin\\Debug\\";
Evidence adevidence = AppDomain.CurrentDomain.Evidence;
AppDomain newDomain = AppDomain.CreateDomain("FrameworkDomain", adevidence, domaininfo);
Run Code Online (Sandbox Code Playgroud)
有效,但是当我尝试时CreateInstance,我得到了一个 TargetInitation 异常
我也尝试过:
Thread.GetDomain().SetupInformation.PrivateBinPath = "D:\\.....\\bin\\Debug\\";
Run Code Online (Sandbox Code Playgroud)
这听起来“特别”,但对我来说很好,但它不起作用......
我真的觉得我必须给出D:\\.....\\bin\\Debug\\当前 AppDomain 的路径,但它不再可能,因为AppendPrivatePath已经过时了......
有什么帮助吗?
最新版本的 .NET 确实允许在一个进程内创建多个 CLR(垃圾收集器是在 .net 系统范围内还是在应用程序范围内?)。
所以基本上我们可以在一个进程中拥有超过 1 个堆。那么受此更改影响的域有何影响?域是否仍然在一个进程内共享堆?
PS:线程上下文保存在哪里,而上下文切换发生在多处理器操作系统中?
我目前正在尝试制作一个游戏引擎,尝试逐个复制统一功能,用于加载一些脚本,我没有问题,但是当我必须重新加载它们时,单声道编译失败,告诉我DLL是已经访问过,或者无法删除DLL文件。
这是我的代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;
using System.Diagnostics;
using System.Security.Policy;
using System.Security;
using System.Security.Permissions;
public class Proxy : MarshalByRefObject
{
public Assembly GetAssembly(string assemblyPath)
{
try
{
byte[] response = new System.Net.WebClient().DownloadData(assemblyPath);
return Assembly.ReflectionOnlyLoad(response);
}
catch (Exception)
{
return null;
}
}
public Assembly GetAssembly2(string assemblyPath, AppDomain domain)
{
try
{
byte[] bytesDLL = new System.Net.WebClient().DownloadData(assemblyPath);
return domain.Load(bytesDLL);
}
catch (Exception)
{
return null;
// throw …Run Code Online (Sandbox Code Playgroud) 我在 .NET 应用程序中卸载 AppDomain 时遇到问题。
我有以下代码,它只是将 dll 加载到目录中并检查它们是否具有特定属性:
AppDomainSetup info = new AppDomainSetup();
Assembly arAssembly = typeof(AssemblyResolver).Assembly;
info.ApplicationBase = Path.GetDirectoryName(arAssembly.Location);
AppDomain appDomain = AppDomain.CreateDomain("AssemblyResolver", null, info);
//Find all the assemblies with the attribute defined
AssemblyName[] assemblyNames = null;
AssemblyResolver ar = (AssemblyResolver)appDomain.CreateInstanceAndUnwrap(arAssembly.FullName, typeof(AssemblyResolver).FullName) as AssemblyResolver;
assemblyNames = ar.PrivateFindAssembliesWithAttribute(attributeType, path, includeSubdirs);
//Finally unload the AppDomain
AppDomain.Unload(appDomain); <-- HANGS HERE
appDomain = null;
Run Code Online (Sandbox Code Playgroud)
这对于我所有具有相关属性的 dll 来说效果很好。但我有一个 dll,其中包含对第 3 方 dll 的引用(PelcoSDK.dll,请参阅:http ://pdn.pelco.com/sdk#sthash.ERuOPMO6.dpbs )
每当包含此 dll 时,以下行就会冻结:
AppDomain.Unload(appDomain);
Run Code Online (Sandbox Code Playgroud)
通过此链接: https: //social.msdn.microsoft.com/Forums/en-US/3f0f10ae-7fcb-459d-9112-6556a9b5b456/appdomainunload-deadlock ?forum=csharplanguage …
考虑以下小程序,它只是创建一个TransactionScope、打印Transaction.Current、调用另一个 AppDomain 中的方法(需要一段时间执行),然后Transaction.Current在返回时打印。
using System;
using System.Linq;
using System.Runtime.Remoting.Lifetime;
using System.Threading;
using System.Transactions;
namespace TransactionScopeFlowTest
{
class Program
{
static void Main(string[] args)
{
// These times are just to generate the error faster. Normally the initial lease is 5 minutes, meaning the method call
// would have to take 5 minutes to occur, so we speed it up here for demonstration purposes.
LifetimeServices.LeaseManagerPollTime = TimeSpan.FromSeconds(1);
LifetimeServices.LeaseTime = TimeSpan.FromSeconds(1);
LifetimeServices.RenewOnCallTime = TimeSpan.FromSeconds(1);
AppDomain domain …Run Code Online (Sandbox Code Playgroud) .net remoting appdomain transactionscope system.transactions
我仍在尝试了解持续存在的问题,但它几乎可以概括为无法卸载 AppDomain。
它发生在将 ASP.NET WebAPI 部署到 Azure 应用服务期间,我们观察到的情况如下:
“在 w3wp_12396.dmp 中,应用程序 /LM/W3SVC/1523308129/ROOT 的 HttpRuntime 正处于关闭过程中。”
分析内存转储,我们看到设置了IsAbortRequested标志的线程,但它们似乎永远不会完成(!threads此处 WinDbg 的输出: https: //pastebin.com/7CXYcffy)
在内存转储中,我们还看到许多具有“ UNLOAD_REQUESTED ”阶段的 AppDomain,它们似乎从未完成卸载(完整输出!DumpDomain位于: https: //pastebin.com/kahZQuWN)
域 7:000001c67062c800 低频堆:000001c67062cff8 高频堆:000001c67062d088 存根堆:000001c67062d118 阶段:UNLOAD_REQUESTED 安全描述符:000001c6705c5680 名称:/LM/W3SVC/1523308129/ROOT-6-131687140950004974
未检测到死锁!dlk(至少通过 WinDbg SOSEX 插件的命令,通常涵盖大多数死锁情况)
没有代码取消线程中止(没有Thread.ResetAbort()调用)
现在解决问题的唯一方法是终止进程(停止 Azure AppService)。
AppDomain无法卸载的可能原因有哪些?
更新。在线程堆栈中,我们得到一个提示,它可能与我们的自定义 Azure Blob Log4net 附加程序有关,我发现当创建此类附加程序时(每个应用程序一次),它会生成具有以下结构的新线程。 …
我目前正在迁移一个项目,它是从 .Net Framework 到 .Net Core 的测试项目。
在 .Net Framework 中,我们曾经能够做这样的事情来为测试设置 EntryAssembly:
AppDomainManager manager = new AppDomainManager();
FieldInfo entryAssemblyfield = manager.GetType().GetField("m_entryAssembly", BindingFlags.Instance | BindingFlags.NonPublic);
entryAssemblyfield.SetValue(manager, assembly);
AppDomain domain = AppDomain.CurrentDomain;
FieldInfo domainManagerField = domain.GetType().GetField("_domainManager", BindingFlags.Instance | BindingFlags.NonPublic);
domainManagerField.SetValue(domain, manager);
Run Code Online (Sandbox Code Playgroud)
取自这里:https : //dejanstojanovic.net/aspnet/2015/january/set-entry-assembly-in-unit-testing-methods/
由于 AppDomainManager 在 .Net Core 中不再可用,我们如何完成类似的事情,以便Assembly.GetEntryAssembly();返回我想要的而不是测试项目程序集。
我正在开发一个大型 ASP.Net 5 Web 应用程序,我想实现自我更新功能。由于程序可以以不同的方式部署在许多不同的平台上(例如Windows服务,Linux上的systemd服务,Docker容器等......),实现自我更新机制的唯一可行的方法是编写一个主机进程可以加载和卸载主程序DLL及其依赖项。卸载很重要,因为主机程序(更新程序)必须能够在运行时覆盖服务器的 DLL 文件。
以下是我到目前为止所做的工作:我已将主 Web 应用程序的输出类型更改为 Library,并且制作了一个小型加载程序,该程序将该 DLL 及其依赖项加载到 中HostAssemblyLoadContext,然后调用原始Main()方法。服务器应用程序被编程为在启动后几秒钟正常关闭,因此该CreateHostBuilder(args).Build().Run()方法Main()可以返回。之后,我尝试调用HostAssemblyLoadContext.Unload(),但由于某种原因,加载上下文拒绝实际卸载。
这是我的 HostAssemblyLoadContext 实现:
public class HostAssemblyLoadContext : AssemblyLoadContext
{
private readonly AssemblyDependencyResolver _resolver;
public HostAssemblyLoadContext(string pluginPath) : base(isCollectible: true)
{
_resolver = new AssemblyDependencyResolver(pluginPath);
}
protected override Assembly? Load(AssemblyName name)
{
string? assemblyPath = _resolver.ResolveAssemblyToPath(name);
if (assemblyPath != null)
return LoadFromAssemblyPath(assemblyPath);
string filePath = $"{name.FullName.Split(',')[0]}.dll";
if(File.Exists(filePath))
return Assembly.LoadFrom(filePath);
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
我的加载器代码:
[MethodImpl(MethodImplOptions.NoInlining)]
private static …Run Code Online (Sandbox Code Playgroud) 我有一个应用程序,它加载程序集并查找类型,这些类型是应用程序引用的另一个程序集A1中定义的类C1的子类.我在A1中定义了一个类型T,它是C1的子类,但是当我使用Assembly.Load(...)加载A1时,在TI实例上调用t.IsSubclassOf(typeof(C1))得到false.我注意到当前appdomain中有2个程序集A1的实例,如果我从其中一个实例中获取C1类型而不是两个实例,则t.IsSubclassOf(C1)可以工作.我不太明白这种行为,任何人都可以解释一下吗?此外,我如何修复我的应用程序,以便无论是加载A1还是其他程序集来查找C1的子类型?
appdomain ×10
c# ×7
.net ×4
assemblies ×2
.net-3.5 ×1
.net-core ×1
asp.net ×1
asp.net-core ×1
azure ×1
clr ×1
dll ×1
domainunload ×1
heap-memory ×1
mono ×1
mstest ×1
remoting ×1