c# - 卸载 AppDomain 后,所有程序集都被释放,除了一个

标签 c# .net-assembly appdomain

因此,在对如何对 c# 脚本编译器进行沙箱化以便加载的程序集仅加载到沙箱 ​​AppDomain 而不是我的主要 AppDomain 中进行了大量研究之后,我遇到了所有 dll 的问题创建的在卸载沙箱 AppDomain 时被卸载,除了一个。该脚本来自如下所示的脚本:

return new Func<List<int>,int>
(
  (list) => 
  {
    var total = 0;
    foreach (int i in list) 
    {
      total += i;          
    }
    return total;
  }
);

现在,脚本的返回结果是它们最终都在字典中返回到主 AppDomain。其余脚本都返回简单的可序列化对象或基元,正如我所说,它们的所有程序集都正确卸载,并且我能够在主域仍处于事件状态的情况下删除它们。这个特定的返回是否有可能必须将创建的程序集“传递”回主 AppDomain,因为它的值是 Func?有没有办法解决这个问题?

我首先拥有沙箱的原因是,在一组脚本运行后,我可以处置执行它们的对象,并且处置方法卸载沙箱域并删除所有创建的程序集。我希望能够在像 Web 服务器这样的持续运行环境中使用它,在该环境中,程序集的构建存在问题,目前,每次脚本集运行并返回 Func 时,我都会有一个挥之不去的程序集。我宁愿在使用该库的文档旁边没有星号,所以欢迎任何想法。

作为引用,这是我编译脚本的代码:

var provider = new CSharpCodeProvider(new Dictionary<string, string>() { { CompilerOptionName, CompilerOptionVersion  } });
        var compilerParams = new CompilerParameters { GenerateExecutable = false, GenerateInMemory = false };
        compilerParams.ReferencedAssemblies.AddRange(References);
        compilerParams.TempFiles = new TempFileCollection(BinPath);
        compilerParams.OutputAssembly = Path.Combine(BinPath,
            Utilities.AssemblyPrefix + ProfigurationExe.Profiguration.ID + "_" + Action.ID + "_Script" + Utilities.DllExt);
        // If no object is returned by user code, enter in a return null to satisfy returning an object for
        // default code template.  If they do have a return that will return first.
        Code = Code + ReturnNull;
        var parameterString = BuildParameterString();
        parameterString = !String.IsNullOrEmpty(parameterString) ? ", " + parameterString : String.Empty;

        // If someone simply imports namespaces separated by spaces, commas, or semicolons, create a proper using statement
        if (!String.IsNullOrEmpty(Imports) && !IsUsingRegex.IsMatch(Imports))
        {
            Imports = String.Join("; ", Imports.Split(" ,;".ToCharArray()).Select(s => Using + " " + s)) + "; ";
        }
        FinalCode = String.Format(Imports + CodeTemplate,
            new object[] {DefaultNamespace, ClassName, DefaultMethod, parameterString, Code});
        // This just is a variable of the code that will be compiled, with all spaces and line breaks removed
        var debugFriendlierFinalCode = U.CompressWhiteSpaceRegex.Replace(FinalCode.Replace("\r", String.Empty).Replace("\n", String.Empty), U.OneSpace);
        // Note that we are adding the import fields to the beginning in case user wants to import namespaces (and not have to always use fully qualified class names)
        var results = provider.CompileAssemblyFromSource(compilerParams, FinalCode);
        Assembly = results.CompiledAssembly;
        if (!results.Errors.HasErrors)
        {
            return Assembly;
        }


        // If there were compiler errors, aggregrate them into an exception.
        var errors = new StringBuilder("Dynamic Code Compiler Errors :\r\n");
        foreach (CompilerError error in results.Errors)
        {
            errors.AppendFormat("Line {0},{1}\t: {2}\n",
                error.Line, error.Column, error.ErrorText);
        }
        throw new ProfigurationException(errors.ToString());

最佳答案

Func 是可序列化的,并且正在按照您的意图进行复制。但它指向驻留在您要卸载的程序集内部的代码。这就是程序集也在父 AppDomain 中加载的原因。

不确定推荐什么。我希望您不能卸载正在使用的代码是有道理的。

关于c# - 卸载 AppDomain 后,所有程序集都被释放,除了一个,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24576272/

相关文章:

c# - Unity3d开发: JNI ERROR (app bug): accessed stale local reference 0x200001 (index 0 in a table of size 0)

sql-server-2008 - 支持 ASP.NET\C# 项目上的多个程序集

c# - 如何处理跨应用域数据交换

c# - 获取 AppDomain 中所有可用命名空间的列表

c# - ASP.Net 曾经在默认的 AppDomain 中运行过吗?

c# - 针对 ActiveDirectory 进行身份验证

c# - 如何根据另一个Group by的总和进行Group by?

c# - 如何等待后台 worker 完成处理?

c# - 从资源加载的程序集引发无法加载文件或程序集

c# - 本应兼容的不兼容 .NET Standard 程序集?