是否可以将lambda表达式作为IL字节流传递给辅助AppDomain,然后使用DynamicMethod将其组装回那里,以便可以调用它?
我不太确定这是一个正确的方法,所以这是(详细的)原因我问这个问题...
在我的应用程序中,有很多情况需要加载几个程序集进行反射,因此我可以确定接下来要对它们做些什么.问题部分是我需要能够在完成反射之后卸载组件.这意味着我需要使用另一个加载它们AppDomain.
现在,我的大多数情况都有点类似,但不完全相同.例如,有时我需要返回一个简单的确认,有时我需要从程序集中序列化资源流,有时我还需要进行一两次回调.
因此,我最终AppDomain一遍又一遍地编写相同的半复杂临时创建代码,并实现自定义MarshalByRefObject代理以在新域和原始域之间进行通信.
由于这不再是可以接受的,我决定编写一个AssemblyReflector可以这样使用的类:
using (var reflector = new AssemblyReflector(@"C:\MyAssembly.dll"))
{
bool isMyAssembly = reflector.Execute(assembly =>
{
return assembly.GetType("MyAssembly.MyType") != null;
});
}
Run Code Online (Sandbox Code Playgroud)
AssemblyReflector将AppDomain凭借自动卸载IDisposable,并允许我执行一个透明地Func<Assembly,object>将反射代码保存在另一个中的-type lambda AppDomain.
问题是,lambdas不能简单地传递给其他域.所以在搜索之后,我发现看起来像是一种方法:将lambda传递给新AppDomain的IL作为IL流 - 这让我想到了原始问题.
这是我尝试过的,但没有用(BadImageFormatException在尝试调用新委托时问题被抛出):
public delegate object AssemblyReflectorDelegate(Assembly reflectedAssembly);
public class AssemblyReflector : IDisposable
{
private AppDomain _domain;
private string _assemblyFile;
public AssemblyReflector(string fileName) { ... }
public void Dispose() { ... …Run Code Online (Sandbox Code Playgroud) 我有一个ac#evaluator,它使用(我认为).Net 4新的简化沙盒appdomain模型来托管c#程序集,其余的是远程处理.创建appdomain的调用是
Evidence ev = new Evidence();
ev.AddHostEvidence(new Zone(SecurityZone.Trusted));
PermissionSet pset = SecurityManager.GetStandardSandbox(ev);
AppDomainSetup ads = new AppDomainSetup();
ads.ApplicationBase = "C:\\Sandbox";
// Create the sandboxed domain.
AppDomain sandbox = AppDomain.CreateDomain(
"Sandboxed Domain",
ev,
ads,
pset,
null);
Run Code Online (Sandbox Code Playgroud)
c#eval嵌入在服务器应用程序中,但我不想让沙箱得到很多控制,除非它是调用者.我正在寻找的是关于如何提供来自呼叫者的证据的澄清.我正在寻求建议和指导.
任何帮助,将不胜感激.
我在调试调用另一个AppDomain的应用程序时遇到问题,因为如果在其他AppDomain正在执行的任何操作中发生异常,则异常会冒泡并导致Visual Studio 2010无论如何都会中断.
我正确地包装了抛出a的方法调用try/catch,并且当我正常运行应用程序(ASP.NET MVC应用程序)时正常捕获异常,但是w3wp.exe在Visual Studio 2010中调试时,它总是在方法上中断调用那个抛出,即使应该被抓住,我也无法通过异常.
我试图装饰外部方法,其中try/catch和throw方法调用完成,[DebuggerStepThrough]但绝对没有效果.执行"继续(F5)","跳过(F10)"或"跳出(F11)"也不执行任何操作; Visual Studio只是暂停了一下,然后在相同的位置再次中断,但具有完全相同的异常.一旦Visual Studio在发生异常的位置停止,似乎绝对没有办法继续前进.
我正在做的就是调用assembly.GetExportedTypes()如果导出的类型引用了一个无法找到的程序集(我想忽略的情况),可能会抛出.抛出的异常是:
FileNotFoundException越过了本机/托管边界
我正在抓住FileNotFoundException,正如我所说的,这在运行应用程序时有效,但在调试时无效.如何让调试器理解我assembly.GetExportedTypes()抛出一个老鼠屁股?
我认为通过取消选中Visual Studio 2010中的选项"在异常时跨越AppDomain或托管/本地边界(仅限托管)"(在"调试">"常规"下)中的选项来解决此问题,但此问题刚刚再次出现.我已经撒了[DebuggerStepThrough],[DebuggerStepperBoundary]并且[DebuggerNonUserCodeAttribute]对所讨论的方法没有任何影响.
我的印象是AppDomains彼此隔离.似乎在StackOverException的情况下,情况并非如此.
为了演示这个问题,我创建了一个简单的控制台应用程序,其唯一目的是生成一个新的AppDomain,我在其中加载一个非常简单的程序集并调用其中一个方法.此方法恰好抛出StackOverflowException.这导致我的控制台应用程序毫不客气地终止.
我希望的行为是"子"AppDomain崩溃并在这样的异常上刻录,但是保持我的控制台应用程序在"父"AppDomain中运行,没有受到损坏.
这可能吗?
更新:这是一些代码.两个异常处理程序都没有被命中.
class Program
{
static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
// create app domain
var domain = AppDomain.CreateDomain("MyDomain");
// create a component
var component = (MyComponent)domain.CreateInstanceAndUnwrap(
"AppDomainMonitor.Component",
typeof(MyComponent).FullName);
// create a thread from a method on this component
var thread = new Thread(component.CauseStackOverflow);
// start the thread
thread.Start();
Console.ReadKey();
}
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
// never hit
}
}
public class MyComponent : MarshalByRefObject
{
public void CauseStackOverflow()
{
try
{ …Run Code Online (Sandbox Code Playgroud) 有没有办法使用插件系统(我会使用IoC容器)在运行时加载一个版本的程序集,然后在AppDomain运行时替换该DLL?我不想重启应用程序.
MEF会做这样的事情吗?
我正在尝试使用.NET 4.5的新正则表达式匹配超时,特别是AppDomain.CurrentDomain.SetData具有"REGEX_DEFAULT_MATCH_TIMEOUT"属性的全局变体via (将您传递TimeSpan给正则表达式构造函数的变体工作正常).
当我使用这个main方法创建一个新的控制台应用程序:
static void Main(string[] args)
{
AppDomain.CurrentDomain.SetData("REGEX_DEFAULT_MATCH_TIMEOUT",
TimeSpan.FromSeconds(3));
var m = System.Text.RegularExpressions.Regex.Match(
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "^(x+x+)+y$");
}
Run Code Online (Sandbox Code Playgroud)
它按预期工作:三秒后,它会抛出一个RegexMatchTimeoutException.
但是,如果我创建一个空的MVC 4应用程序,请添加一个HomeController和此操作方法:
public ActionResult Index()
{
AppDomain.CurrentDomain.SetData("REGEX_DEFAULT_MATCH_TIMEOUT",
TimeSpan.FromSeconds(3));
var m = System.Text.RegularExpressions.Regex.Match(
"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "^(x+x+)+y$");
return View();
}
Run Code Online (Sandbox Code Playgroud)
并且访问http://localhost:XXXXX/没有异常被抛出并且匹配尝试继续.(如果你等待足够长的时间,它会最终完成,然后抱怨缺少的观点.这需要veeery长虽然).
调用SetData在Global.asax的Application_Start(),而不是控制操作中不会使超时要么发生.
我正在处理一个错误,在应用程序关闭之前,代码并不总是被执行.代码位于AppDomain.CurrentDomain.DomainUnload事件的处理程序中.
我找到了一个有同样问题的人发来的帖子
"当您的默认应用程序域发生DomainUnload事件时,您的代码已停止执行.您可以使用默认AppDomain上的ProcessExit事件执行所需操作."
这对我有用,但我想知道为什么.我无法在这些事件或它们之间的差异上找到太多.我也想知道我是否需要订阅这两个,或者ProcessExit是否足够.
编辑:
我想添加更多信息以使其更有用.
我遗漏了在他们自己的AppDomain中创建新线程.因为我希望这个代码不仅在父进程完成时运行,而且在每个线程完成时运行,我需要订阅DomainUnload事件来处理每个线程何时完成,以及ProcessExit事件在父进程完成时捕获.
我们有一个ASP.NET MVC 4应用程序,它链接到传统的本机代码.问题是这个遗留代码具有在启动时构建的全局静态代码,但由于本机代码对App Domains一无所知,因此在重新加载App Domain时不会重新初始化该代码.在重新启动应用程序池进程之前,这会导致我们的应用程序中出现不正确的行为或崩溃.
因此,我想强制应用程序池在我们的应用程序的App Domain被回收时进行回收.IIS中是否有这样的设置,或者是否正在卸载域时我可以在我的应用程序中调用代码?
关于我的设置的一些信息,
更新
根据下面的答案,我连接到AppDomain卸载事件,并使用类似于以下的代码来回收应用程序池.
try
{
// Find the worker process running us and from that our AppPool
int pid = Process.GetCurrentProcess().Id;
var manager = new ServerManager();
WorkerProcess process = (from p in manager.WorkerProcesses where p.ProcessId == pid select p).FirstOrDefault();
// From the name, find the AppPool and recycle it
if ( process != null )
{
ApplicationPool pool = (from p in manager.ApplicationPools where p.Name == process.AppPoolName …Run Code Online (Sandbox Code Playgroud) 我有一个ac#应用程序,它依赖于第三方非托管程序集来访问某些硬件.
非托管代码存在内存泄漏,每次访问后内存消耗会增加~10mb.问题是众所周知的; 没有bugfix可用.
有没有办法可以继续使用这个程序集而无需定期重启?
我尝试创建一个单独的AppDomain,将有问题的代码加载到该AppDomain中appDomain.CreateInstanceAndUnwrap(),然后通过以下方式卸载域AppDomain.Unload().但是,这显然不会释放该域使用的非托管内存,只释放托管内存.
我还可以将应用程序拆分为两个独立的部分,并仅重新启动具有非托管dll的部分.然而,这将意味着重大的重新设计,并且可能导致大量的减速,因为必须在这两个部分之间交换大量数据.
是否有另一种方法可以驯服这个漏出的程序集并强制它释放内存而不重新启动.
我有一个.NET MVC Web应用程序,需要时间才能正常关闭,因此每当IIS应用程序域被回收时(即,新实例在新实例关闭时接收所有新请求,等待未完成的请求完成)我需要阻止此应用程序关闭,直到我的应用程序的当前异步后台工作(包含没有未完成的请求)已完成.IRegisteredObject(参见http://blog.stephencleary.com/2014/06/fire-and-forget-on-asp-net.html)提供了这种阻止功能,但是,我的进程似乎总是在与我的阻塞不一致的情况下死亡时间和IIS设置.
我看到这篇文章(IRegisteredObject没有按预期工作)解释了IIS关闭时间限制的重要性,但是,当IRegisteredObject似乎阻塞了一段时间后,我无法让循环阻止2小时所需的时间(也不是我可以通常得到基于各种设置有意义的结果).
下面是一个IRegisteredObject的简单实现,它带有我一直用于测试的后台线程:
public class MyRegisteredObject : IRegisteredObject
{
public void Register()
{
HostingEnvironment.RegisterObject(this);
Logger.Log("Object has been registered");
}
// the IRegisteredObject.Stop(...) function gets called on app domain recycle.
// first, it calls with immediate:false, indicating to shutdown work, then it
// calls 30s later with immediate:true, and this call 'should' block recycling
public void Stop(bool immediate)
{
Logger.Log("App domain stop has been called: "
+ (immediate ? "Immediate" : "Not Immediate") …Run Code Online (Sandbox Code Playgroud)