插件式框架探索

上传人:j****9 文档编号:45958704 上传时间:2018-06-20 格式:DOC 页数:15 大小:178.07KB
返回 下载 相关 举报
插件式框架探索_第1页
第1页 / 共15页
插件式框架探索_第2页
第2页 / 共15页
插件式框架探索_第3页
第3页 / 共15页
插件式框架探索_第4页
第4页 / 共15页
插件式框架探索_第5页
第5页 / 共15页
点击查看更多>>
资源描述

《插件式框架探索》由会员分享,可在线阅读,更多相关《插件式框架探索(15页珍藏版)》请在金锄头文库上搜索。

1、【插件式框架探索系列插件式框架探索系列】应用程序域(应用程序域(AppDomain) Posted on 2010-06-30 15:03 Kolor 阅读(1252) 评论(9) 编辑 收藏 所属分类: DotNet, WPF 应用程序域(AppDomain)已经不是一个新名词了,只要熟悉.net 的都知道它的存在,不过我们还是先一起来重新认识下应用程序域吧,究竟它是何方神圣。应用程序域应用程序域众所周知,进程是代码执行和资源分配的最小单元,每个进程都拥有独立的内存单元,而进程之间又是相互隔离的,自然而然,进程成为了代码执行的安全边界。一个进程对应一个应用程序是一个普遍的认知,而.net 却

2、打破了这一惯例,因为它带来了应用程序域这一全新的概念,CLR 可使用应用程序域来提供应用程序之间的隔离,而一个进程中可以运行多个应用程序域,也就是说只要使用应用程序域,我们可以在一个进程中运行多个应用程序,而不会造成进程间调用或进程间切换等方面的额外开销。是不是觉得应用程序域是个很神奇的东东了,别急,我们再来看看它的隔离特性又为我们带来了什么。优势优势首先,应用程序域之间是不相互影响的,它是天生的异常隔离机制。也就是说,在一个应用程序域中出现的错误不会影响到其他应用程序域,因为类型安全的代码不会导致内存错误。其次,它能够在运行时动态的加载和卸载程序集。我们都知道,在.net 世界中,加载器一旦

3、加载了程序集,那么它将一直存在于应用程序的整个生命周期中,而应用程序域则改变了这一切,它为我们提供了卸载程序集的能力。最后,应用程序域可以单独实施安全策略和配置策略。说白了就是可以为每个应用程序域配置相应的权限,以更好的管理应用程序。另外值得注意的是,应用程序域和线程之间不具有一对一的相关性。在任意给定时间,在单个应用程序域中可以执行多个线程,而特定线程并不局限在单个应用程序域内。也就是说,线程可以自由跨越应用程序域边界,如果没有主动新启线程,那么多个应用程序域依然运行在同一个线程中。总的来说,应用程序域形成了托管代码的隔离、卸载和安全边界。而这些特性带给一个插件式框架的将是异常隔离、动态加载

4、卸载插件和更安全的插件运行环境。由于这篇文章的定位是针对框架设计结合应用程序域的特性,因此假设你已经对应用程序域有了一定的了解了,下面通过示例,让我们一步一步来认识应用程序域的这些特性。创建和卸载创建和卸载 AppDomain使用 C#我们可以用如下的方式创建一个应用程序域,并在新域中执行一段代码:AppDomain domain = AppDomain.CreateDomain(“Hello AppDomain!“);domain.DoCallBack(new CrossAppDomainDelegate() =Window win = new WindowWidth = 300,Heigh

5、t = 100,Content = AppDomain.CurrentDomain.FriendlyName;win.Show(););运行后可以看到在新域中创建的 Window 展示如下:卸载应用程序域则可以通过 AppDomain 静态方法 AppDomain.Unload(domain)实现,就是这么简单。配置域加载方式配置域加载方式如果你运行了上面这段代码,是不是发现新域创建的 Window 过了好久才呈现出来,这是怎么回事呢,简单来说,这是因为.net 加载器默认的行为是在每个域里都会重新加载引用的程序集(包括 Framework 本身除了 mscorlib 外的程序集),当然我们可

6、以更改这种行为,不过在这之前我们先来了解下一个新概念”domain neutrality”, 详细资料可以看这篇文章 Domain Neutral Assemblies,简单来说它拥有跨域共享程序集的能力,这就避免了重复加载的损耗,我们可以通过为程序入口 main 函数添加 LoaderOptimization 标签修改默认加载方式:System.STAThreadAttribute()System.Diagnostics.DebuggerNonUserCodeAttribute()LoaderOptimization(LoaderOptimization.MultiDomainHost)pu

7、blic static void Main()AppDomainTest.App app = new AppDomainTest.App();app.InitializeComponent();app.Run();重新编译运行,速度有了明显的提升吧。LoaderOptimization 有三种方式(SingleDomain, MultiDomain 和 MultiDomainHost),在 Domain Neutral Assemblies 中均有详细的解译,有兴趣的朋友可以看下,此处就不再重述了。异常隔离异常隔离 对于插件式框架而言,异常隔离是非常重要的,这是保证一个框架稳定性的必要特性。下

8、面我们来看看使用应用程序域如何实现异常隔离。首先我们来模拟在新创建的域中抛出异常:AppDomain domain = AppDomain.CreateDomain(“Hello AppDomain!“);domain.DoCallBack(new CrossAppDomainDelegate() =Window win = new WindowWidth = 300,Height = 100,Content = AppDomain.CurrentDomain.FriendlyName;win.Loaded += (obj, arg) =throw new Exception(“test ex

9、ception.“);win.Show(););这里采用的是在 Window loaded 事件中直接抛出异常达到模拟效果,OK,编译运行,很不幸,成功挂掉。这是因为新域中未处理的异常,最终都会抛至默认域,进而导致崩溃。要验证这一点,很容易,我们只要在默认域中添加 AppDomain.CurrentDomain.UnhandledException 事件处理就可以截获到新域中抛出的异常,可惜在此你只能截获却无法改变崩溃的结果。那么如何才能处理掉这个异常,在默认域或者新域中注册System.Windows.Threading.Dispatcher.CurrentDispatcher.Unhand

10、ledException 事件处理,示例如下:AppDomain domain = AppDomain.CreateDomain(“Hello AppDomain!“);System.Windows.Threading.Dispatcher.CurrentDispatcher.UnhandledException += (obj, arg) =arg.Handled = true;MessageBox.Show(arg.Exception.Message);AppDomain.Unload(domain);domain.DoCallBack(new CrossAppDomainDelegate

11、() =Window win = new WindowWidth = 300,Height = 100,Content = AppDomain.CurrentDomain.FriendlyName;win.Loaded += (obj, arg) =throw new Exception(“test exception.“);win.Show(););注意到最关键的 arg.Handled = true 这一句,它的意义在于告诉系统这个事件已经被处理过了,不要再往下传递了,最后主动把新域卸载掉,而默认域则仍然正常运行着,如此便达到了异常隔离的效果。组合不同域中的插件组合不同域中的插件 假设所有

12、的插件都处于不同的域中,那么如何组合它们呢,即如何将不同域中的插件同时呈现到一个容器中。众所周知,要实现对象在域之间传递,对象必须是可序列化的或者是继承自 MarshalByRefObject 的类型,然而UI 控件对此却是无能为力了, 在此就需要微软的 Addin 框架帮助了,虽然大家都觉得 Addin 框架复杂、难用,但是里面有好些东西还是很有用处的,比如这里将要用到的 FrameworkElementAdapters 类,它提供了两个静态方法ContractToViewAdapter 和 ViewToContractAdapter 用于实现 FrameworkElement 和INati

13、veHandleContract 之间的相互转换,传说中这种转换是通过句柄实现的。还是用例子来说明如何让插件跨域呈现吧,首先添加 System.Addin.Contract.dll 和 System.Windows.Presentation.dll 两个引用,然后编写如下代码AppDomain domain = AppDomain.CreateDomain(“test“);domain.DoCallBack(new CrossAppDomainDelegate() =/ 在新域中创建 Button 控件Button btn = new Button Content = “test“ ;/ 将

14、Button 控件转换为 INativeHandleContractINativeHandleContract ict = FrameworkElementAdapters.ViewToContractAdapter(btn);AppDomain.CurrentDomain.SetData(“testbtn“, ict););/ 在主域中获取新域中的 INativeHandleContract 对象INativeHandleContract iContract = domain.GetData(“testbtn“) as INativeHandleContract;/ 将 INativeHan

15、dleContract 对象转换回 FrameworkElementFrameworkElement ctrl = FrameworkElementAdapters.ContractToViewAdapter(iContract);Application.Current.MainWindow.Content = ctrl;运行结果如下,新域中创建的控件成功的呈现在了主域中至于域中的权限配置部分,将在下篇中讲述。谨以此记录成长的脚步,同时和大家一起分享快乐。【插件式框架探索系列插件式框架探索系列】使用多使用多 UI 线程提升性能线程提升性能 Posted on 2010-06-23 21:22

16、Kolor 阅读(1623) 评论(5) 编辑 收藏 所属分类: DotNet, WPF 了解 WPF 线程模型的都知道,UI 线程负责呈现和管理 UI,而 UI 元素(派生自DispatcherObject)只能由创建该元素的线程来访问,这就导致了一些耗时的 UI 操作将影响到整个应用程序性能,未响应及漫长的等待有时会令人抓狂,而 UI 线程一度成为了不可越逾的鸿沟。对于框架来说,一个插件的行为不应该影响到其它插件及整个平台的稳定性,后来在看了Running WPF Application with Multiple UI Threads和DispatcherObject 与 WPF 线程模型两篇文章后,思维一下子就打开了,前一篇讲的是在 WPF 应用程序中使用多个 UI 线程,如果每个独立的插件都处于不同的 UI 线程,自然性能会有所提升,而后一篇则深入的分析了 win32 的消息循环和 wpf 的线程模型,非常透彻。下面是创建新 UI 线程的方法Thread

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 中学教育 > 初中教育

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号