Tag: appdomain

Cross AppDomain最低通信性能损失是多少?

我正在尝试最小化在同一台计算机上跨AppDomain进行通信的性能损失。 在我的玩具示例中,A类在AppDomain 1中加载。它创建一个AppDomain 2并在那里加载一个Class 2实例(Class 2inheritance自MarshalByRef)获取代理。 然后,Class 1重复调用代理上不返回任何值的方法。 我得到以下结果: 没有AppDomains,这两个类都加载在同一个AppDomain中,第一个调用是第二个方法(该方法没有参数): 2400万个方法调用/秒 如上所述的两个AppDomain,方法没有参数或“出血”字符串参数: 340.000方法调用/秒 如上所述的两个AppDomain,一个可序列化参数(两个字符串的数组): 64.000个方法调用/秒 虽然我理解2和3之间的性能损失(序列化),但我真的不明白为什么从案例1到案例2的速度要慢100倍 。 据我所知,一旦创建了代理,所有后续的方法调用必须非常快,因为没有数据从一个AppDomain编组到另一个AppDomain。 现在有人为什么要通过AppDomains进行通信这么慢? 难道我做错了什么? PS1。 我对此的唯一提示是:“跨越AppDomain边界的成本令人尴尬。” 我猜他指的是序列化…… PS2。 我不计算AppDomain或代理创建时间(我的基准测试从第一个方法调用开始) PS3。 我在WinXP SP3机器上使用.NET 3.5。 我也试过.NET 4.0 Beta 1没有显着差异。

AppDomains之间的通信

我们正在构建一个应用程序(WinForms,.NET 3.5),它将“插件”DLL加载到辅助AppDomain中。 辅助AppDomain需要偶尔与第一个AppDomain通信(更具体地说,从主AppDomain中创建的对象调用或获取数据)。 我已经阅读了有关AppDomains的大部分内容以及它们之间的通信。 到目前为止,我见过的唯一简单的解决方案是从MarshalByRefObjectinheritance并将TransparentProxy传递到第二个AppDomain,在Proxy上调用方法。 此方法有其缺点(例如,在框架类型的情况下,或者从已经从其他类inheritance的类型,静态字段/类等等,并不总是可以从MBROinheritance)。 由于当前的通信点非常不变(只有2-3个需要通信的场景),我考虑创建一个具有以下属性的简单Mediator类: 将在1st(Main)AppDomain中创建。 只能作为主要AppDomain中创建的“Real”对象的“消息传递器”。 将inheritance自MBRO,并将其代理引用发送到第二个AppDomain。 将调用此代理对象上的方法,然后调用第一个AppDomain中“真实”对象上的方法。 我的问题 – 这看起来像是一个逻辑设计吗? 更重要的是,WCF或任何其他通信框架中是否已存在调解器/消息传递器类? 它似乎是一个通用的概念,我想知道是否有类似的东西。

消息泵和AppDomains

我有一个C#(FFx 3.5)应用程序,它将DLL作为插件加载。 这些插件加载在单独的AppDomain中(出于很多原因,这种架构无法更改)。 这一切都很好。 我现在需要从其中一个插件中显示一个Dialog。 请记住,我无法将对话框Form返回到主应用程序并将其显示在那里(当前基础结构不支持它)。 失败1 在我的DLL中,我创建了一个Form并称为Show。 对话框轮廓显示但没有绘制,它不响应鼠标事件。 我假设这是因为DLL在一个单独的AppDomain中,并且应用程序的消息泵以某种方式无法将消息发送到新表单。 失败2 在我的DLL中,我创建了一个Form并调用了ShowDialog,所有权利都应该为对话框创建一个内部消息泵。对话框显示并响应点击(万岁),但似乎主应用程序不再处理或调度Windows消息因为它退出绘画而不再响应鼠标事件。 由于某种原因,现在似乎主app的消息泵没有调度。 失败3 在我的DLL中,我创建了一个Form并调用了Application.Run。 这肯定会创建一个完整的第二个消息泵。 我得到了与失败2相同的行为 – 对话行为,但调用应用程序没有。 有关这里到底发生了什么的想法,以及如何从其他AppDomain的DLL显示对话框并让调用者和被调用者仍然响应并正确绘制?

如何使用C#正确卸载AppDomain?

我有一个应用程序加载我无法控制的外部程序集(类似于其他人创建和开发主应用程序使用的程序集的插件模型)。 它通过为这些程序集创建新的AppDomain来加载它们,然后在使用程序集完成后,主AppDomain将卸载它们。 目前,它简单地卸载这些组件 try { AppDomain.Unload(otherAssemblyDomain); } catch(Exception exception) { // log exception } 但是,有时会在卸载过程中抛出exception,特别是CannotUnloadAppDomainException 。 根据我的理解,这是可以预料到的,因为由于非托管代码仍在执行或线程在finally块中的情况,子域AppDomains中的线程无法强制中止 : 当线程调用Unload时,目标域将标记为卸载。 专用线程尝试卸载域,并且域中的所有线程都将中止。 如果线程没有中止,例如因为它正在执行非托管代码,或者因为它正在执行finally块,那么在一段时间之后,在最初调用Unload的线程中抛出CannotUnloadAppDomainException。 如果最终无法中止的线程结束,则不会卸载目标域。 因此,在.NET Framework 2.0版域中不保证卸载,因为它可能无法终止执行线程。 我担心的是,如果没有加载程序集,那么它可能会导致内存泄漏。 如果出现上述exception,可能的解决方案是杀死主应用程序进程,但我宁愿避免这种激烈的行为。 我还在考虑重复卸载电话以进行一些额外的尝试。 也许像这样的约束循环: try { AppDomain.Unload(otherAssemblyDomain); } catch (CannotUnloadAppDomainException exception) { // log exception var i = 0; while (i < 3) // quit after three tries { Thread.Sleep(3000); […]

卸载默认应用程序域的事件?

是否有卸载事件,或任何事件,通知,消息,机制或挂钩,我可以用来在“默认”应用程序域卸载之前得到通知? 我有代码需要知道什么时候应用程序域(几乎总是默认域)结束。 注意:我不知道开发人员在使用我的代码时会创建什么样的应用程序。 它可能是: 控制台应用程序 一个WinForms应用程序 一个ASP.net应用程序 一个ASP.net网站 运行时可调用包装器(RCW)COM对象 Windows资源管理器shell扩展 或Windows服务 无论哪种方式,我需要知道域何时关闭,所以我可以做一些“东西” 。 我不会要求用户调用任何类型的“关机”或“清理”方法。 (另外,建议用户自己调用方法时不会回答这个问题:当我正在运行的应用程序域关闭时,该问题是关于通知的)。 也可以看看 卸载默认AppDomain的事件? 如何在最终确定静态变量之前得到通知

如何从另一个appDomain调用类的方法

我的应用程序想要调用来自另一个AppDomain的类的方法。 AppDomain env = AppDomain.CreateDomain( “test”, null, new AppDomainSetup() { ApplicationName = “test” } ); Assembly a = Assembly.LoadFrom(“d:\\testenv1\\test2.dll”); //env.AssemblyResolve += new ResolveEventHandler(env_AssemblyResolve); env.Load(a.FullName); ObjectHandle o = env.CreateInstance(a.FullName, “Test2.Class1″); 现在我有Test2.Class1的对象句柄,但我不知道如何调用Class1类的“action”方法。 “action”方法喜欢这个: public void action() { Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + ” ok”); } 我试图使用o.unwrap()方法来获取对象的引用,但似乎对象已被转移到当前域,因此“action”方法的输出打印当前域名。

如何为.NET应用程序域重新加载程序集?

我们正在加载一个读取配置文件的程序集(DLL)。 我们需要更改配置文件,然后重新加载程序集。 我们看到第二次加载组件后,配置没有变化。 有谁看到这里有什么问题? 我们在配置文件中省略了读取的细节。 AppDomain subDomain; string assemblyName = “mycli”; string DomainName = “subdomain”; Type myType; Object myObject; // Load Application domain + Assembly subDomain = AppDomain.CreateDomain( DomainName, null, AppDomain.CurrentDomain.BaseDirectory, “”, false); myType = myAssembly.GetType(assemblyName + “.mycli”); myObject = myAssembly.CreateInstance(assemblyName + “.mycli”, false, BindingFlags.CreateInstance, null, Params, null, null); // Invoke Assembly object[] Params = […]

静态变量实例和AppDomains,发生了什么?

我有 public static class A { public static string ConnString; } [Serializable] public class Test{ // Accesing A’s field; public string ConnString{get{return A.ConnString;}set{A.ConnString=value;}} } void Main() { A.ConnString = “InitialString”; // I set A.ConnString in the current domain var newDomain = AppDomain.CreateDomain(“DomNew”); Test TObj = newDomain.CreateInstanceAndUnwrap(typeof(Test).Assembly.FullName, typeof(Test).FullName) as Test ; TObj.ConnString = “NewDomainString”; // It […]

如何在不使用AppDomains的情况下实现.net插件?

问题陈述:实现一个插件系统,允许覆盖关联的程序集(避免文件锁定)。 在.Net中,可能无法卸载特定程序集,只能卸载整个AppDomain。 我发布这个是因为当我试图解决问题时,每个解决方案都参考了使用多个AppDomain。 多个AppDomain很难正确实现,即使在项目开始时进行架构也是如此。 另外,AppDomains对我不起作用,因为我需要跨域传输Type作为Speech Server worfklow的InvokeWorkflow活动的设置。 不幸的是,跨域发送类型会导致程序集注入本地AppDomain。 此外,这与IIS相关。 IIS具有卷影复制设置,允许执行程序集在加载到内存时被覆盖。 问题是(至少在XP下,没有在生产2003服务器上测试)当您以编程方式加载程序集时,卷影副本不起作用(因为您正在加载DLL,而不是IIS)。

在不同的AppDomain中加载/卸载程序集

我需要在运行时加载的程序集中执行一个方法。 现在我想在方法调用后卸载那些已加载的程序集。 我知道我需要一个新的AppDomain,所以我可以卸载库。 但在这里,出现了问题。 要加载的程序集是我的插件框架中的插件。 他们根本没有切入点。 我所知道的是它们包含一些实现给定接口的类型。 旧的非AppDomain代码看起来像这样(稍微缩短): try { string path = Path.GetFullPath(“C:\library.dll”); AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; Assembly asm = Assembly.LoadFrom(path); Type[] types = asm.GetExportedTypes(); foreach (Type t in types) { if ((t.GetInterface(“IStarter”) != null) && !t.IsAbstract) { object tempObj = Activator.CreateInstance(t); MethodInfo info = t.GetMethod(“GetParameters”); if (info != null) { return info.Invoke(tempObj, null) as […]