ImageVerifierCode 换一换
格式:DOCX , 页数:15 ,大小:473.98KB ,
资源ID:7115945      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/7115945.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(C#综合细说进程应用程序域与上下文.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

C#综合细说进程应用程序域与上下文.docx

1、C#综合细说进程应用程序域与上下文综合细说进程应用程序域与上下文 引言 本文主要是介绍进程(Process)、应用程序域(AppDomain)、.NET 上下文(Context)的概念与操作。虽然在一般的开发当中这三者并不常用,但熟悉三者的关系,深入了解其作用,对提高系统的性能有莫大的帮助。在本篇最后的一节当中将会介绍到三者与线程之间的关系,希望对多线程开发人员能提供一定的帮助。因为时间仓促,文中有错误的地方敬请点评。目录 一、进程的概念与作用 二、应用程序域 三、深入了解.NET 上下文 四、进程应用程序域与线程的关系 一、进程的概念与作用 进程(Process)是 Windows 系统中的

2、一个基本概念,它包含着一个运行程序所需要的资源。进程之间是相对独立的,一个进程无法访问另一个进程的 数据(除非利用分布式计算方式),一个进程运行的失败也不会影响其他进程的运行,Windows 系统就是利用进程把工作划分为多个独立的区域的。进程可以理解为一个程序的基本边界。1.1 Process 的属性与方法 在 System.Diagnostics 命名空间当中存在 Process 类,专门用于管理进程的开始、结束,访问进程中的模块,获取进程中的线程,设定进程的优先级别等功能。表 1.0 显示了 Process 类的常用属性:属性 说明 BasePriority 获取关联进程的基本优先级。Ex

3、itCode 获取关联进程终止时指定的值。ExitTime 获取关联进程退出的时间。Handle 返回关联进程的本机句柄。HandleCount 获取由进程打开的句柄数。HasExited 获取指示关联进程是否已终止的值。Id 获取关联进程的唯一标识符。MachineName 获取关联进程正在其上运行的计算机的名称。MainModule 获取关联进程的主模块。Modules 获取已由关联进程加载的模块。PriorityClass 获取或设置关联进程的总体优先级类别。ProcessName 获取该进程的名称。StartInfo 获取或设置要传递给 Process 的 Start 方法的属性。St

4、artTime 获取关联进程启动的时间。SynchronizingObject 获取或设置用于封送由于进程退出事件而发出的事件处理程序调用的对象。Threads 获取在关联进程中运行的一组线程 表 1.0 除了上述属性,Process 类也定义了下列经常使用的方法:方法 说明 GetProcessById 创建新的 Process 组件,并将其与您指定的现有进程资源关联。GetProcessByName 创建多个新的 Process 组件,并将其与您指定的现有进程资源关联。GetCurrentProcess 获取新的 Process 组件并将其与当前活动的进程关联。GetProcesses 获

5、取本地计算机上正在运行的每一个进程列表。Start 启动一个进程。Kill 立即停止关联的进程。Close 释放与此组件关联的所有资源。WaitForExit 指示 Process 组件无限期地等待关联进程退出。表 1.1 Process 类的详细信息可以参考 http:/ 下面将举例详细介绍一下 Process 的使用方式 1.2 建立与销毁进程 利用 Start()与 Kill()方法可以简单建立或者销毁进程,下面例子就是利用 Start 方法启动记事本的进程,并打开 File.txt文件。2秒钟以后,再使用 Kill 方法销毁进程,并关闭记事本。1staticvoid Main(stri

6、ng args)2 3 Process process=Process.Start(notepad.exe,File.txt);4 Thread.Sleep(2000);5 process.Kill();6 1.3 列举计算机运行中的进程 在表 1.0 中可以看到,使用 GetProcesses 方法可以获取本地计算机上正在运行的每一个进程列表。而进程的 Id 属性是每个进程的唯一标志,通过下面的方法,可以显示当前计算机运行的所有进程信息。因为篇幅关系,下面例子只获取前 10个进程。1staticvoid Main(string args)2 3var processList=Process.

7、GetProcesses()4.OrderBy(x=x.Id)5.Take(10);6foreach(var process in processList)7 Console.WriteLine(string.Format(ProcessId is:0 t ProcessName is:1,8 process.Id,process.ProcessName);9 Console.ReadKey();10 运行结果 如果已知进程的 Id,就可以通过 GetProcessById 方法获取对应的进程。1staticvoid Main(string args)2 3try 4 5var process

8、=Process.GetProcessById(1772);6 Console.WriteLine(Process name is:+process.ProcessName);7 8catch(ArgumentException ex)9 10 Console.WriteLine(Process is nothing!);11 12 Console.ReadKey();13 同样地,你也可能通过 GetProcessByName 方法获取多个对应名称的进程。注意:如果不能找到当前 ID的进程,系统就会抛出 ArgumentException 异常。所以使用方法 GetProcessById 获

9、取进程时应该包含在 try.catch.之内。1.4 获取进程中的多个模块 在表 1.0 中包含了 Modules 属性,通过此属性可能获取进程中的多个模块。这些模块可以是以*.dll 结尾的程序集,也可以是*.exe 结尾的可执行程序。下面的例子就是通过 Process 的 GetCurrentProcess 方法获取当前运行的进程信息,然后显示当前进程的多个模块信息。1staticvoid Main(string args)2 3var moduleList=Process.GetCurrentProcess().Modules;4foreach(System.Diagnostics.Pr

10、ocessModule module in moduleList)5 Console.WriteLine(string.Format(0n URL:1n Version:2,6 module.ModuleName,module.FileName,module.FileVersionInfo.FileVersion);7 Console.ReadKey();8 运行结果:回到目录 二、应用程序域 使用.NET建立的可执行程序*.exe,并没有直接承载在进程当中,而是承载到应用程序域(AppDomain)当中。应用程序域是.NET 引入的一个新概念,它比进程所占用的资源要少,可以被看作是一个轻量级

11、的进程。在一个进程中可以包含多个应用程序域,一个应用程序域可以装载一个可执行程序(*.exe)或者多个程序集(*.dll)。这样可以使应用程序域之间实现深度隔离,即使进程中的某个应用程序域出现错误,也不会影响其他应用程序域的正常运作。当一个程序集同时被多个应用程序域调用时,会出现两种情况:第一种情况:CLR 分别为不同的应用程序域加载此程序集。第二种情况:CLR 把此程序集加载到所有的应用程序域之外,并实现程序集共享,此情况比较特殊,被称作为 Domain Neutral。2.1 AppDomain的属性与方法 在 System 命名空间当中就存在 AppDomain 类,用管理应用程序域。下

12、面是AppDomain类的常用属性:属性 说明 ActivationContext 获取当前应用程序域的激活上下文。ApplicationIdentity 获得应用程序域中的应用程序标识。BaseDirectory 获取基目录。CurrentDomain 获取当前 Thread 的当前应用程序域。Id 获得一个整数,该整数唯一标识进程中的应用程序域。RelativeSearchPath 获取相对于基目录的路径,在此程序集冲突解决程序应探测专用程序集。SetupInformation 获取此实例的应用程序域配置信息。表 2.0 AppDomain类中有多个方法,可以用于创建一个新的应用程序域,或

13、者执行应用程序域中的应用程序。方法 说明 CreateDomain 创建新的应用程序域。CreateInstance 创建在指定程序集中定义的指定类型的新实例。CreateInstanceFrom 创建在指定程序集文件中定义的指定类型的新实例。DoCallBack 在另一个应用程序域中执行代码,该应用程序域由指定的委托标识。ExecuteAssembly 执行指定文件中包含的程序集。ExecuteAssemblyByName 执行程序集。GetAssemblies 获取已加载到此应用程序域的执行上下文中的程序集。GetCurrentThreadId 获取当前线程标识符。GetData 为指定名

14、称获取存储在当前应用程序域中的值。IsDefaultAppDomain 返回一个值,指示应用程序域是否是进程的默认应用程序域。SetData 为应用程序域属性分配值。Load 将 Assembly 加载到此应用程序域中。Unload 卸载指定的应用程序域。表 2.1 AppDomain类中有多个事件,用于管理应用程序域生命周期中的不同部分。事件 说明 AssemblyLoad 在加载程序集时发生。AssemblyResolve 在对程序集的解析失败时发生。DomainUnload 在即将卸载 AppDomain 时发生。ProcessExit 当默认应用程序域的父进程存在时发生。Reflect

15、ionOnlyAssemblyResolve 当程序集的解析在只反射上下文中失败时发生。ResourceResolve 当资源解析因资源不是程序集中的有效链接资源或嵌入资源而失败时发生。TypeResolve 在对类型的解析失败时发生。UnhandledException 当某个异常未被捕获时出现。表 2.2 下面将举例详细介绍一下 AppDomain的使用方式 2.2 在 AppDomain 中加载程序集 由表 2.1中可以看到,通过 CreateDomain 方法可以建立一个新的应用程序域。下面的例子将使用 CreateDomain 建立一个应用程序域,并使用 Load 方法加载程序集Mo

16、del.dll。最后使用 GetAssemblies 方法,列举此应用程序域中的所有程序集。1staticvoid Main(string args)2 3var appDomain=AppDomain.CreateDomain(NewAppDomain);4 appDomain.Load(Model);5foreach(var assembly in appDomain.GetAssemblies()6 Console.WriteLine(string.Format(0n-,7 assembly.FullName);8 Console.ReadKey();9 运行结果 注意:当加载程序集后,

17、就无法把它从 AppDomain 中卸载,只能把整个AppDomain卸载。当需要在 AppDomain 加载可执行程序时,可以使用 ExecuteAssembly方法。AppDomain.ExecuteAssembly(Example.exe);2.3 卸载 AppDomain 通过 Unload可以卸载 AppDomain,在 AppDomain 卸载时将会触发 DomainUnload事件。下面的例子中,将会使用 CreateDomain 建立一个名为 NewAppDomain 的应用程序域。然后建立 AssemblyLoad 的事件处理方法,在程序集加载时显示程序集的信息。最后建立 D

18、omainUnload事件处理方法,在 AppDomain 卸载时显示卸载信息。1staticvoid Main(string args)2 3/新建名为 NewAppDomain 的应用程序域 4 AppDomain newAppDomain=AppDomain.CreateDomain(NewAppDomain);5/建立 AssemblyLoad 事件处理方法 6 newAppDomain.AssemblyLoad+=7(obj,e)=8 9 Console.WriteLine(string.Format(0 is loading!,e.LoadedAssembly.GetName();

19、10;11/建立 DomainUnload 事件处理方法 12 newAppDomain.DomainUnload+=13(obj,e)=14 15 Console.WriteLine(NewAppDomain Unload!);16;17/加载程序集 18 newAppDomain.Load(Model);19/模拟操作 20for(int n=0;n 10 11 Console.WriteLine(NewAppDomain unload!);12;13/调用委托 14 newAppDomain.DoCallBack(crossAppDomainDelegate);15 AppDomain.

20、Unload(newAppDomain);16 Console.ReadKey();17 18 19staticpublicvoid MyCallBack()20 21string name=AppDomain.CurrentDomain.FriendlyName;22for(int n=0;n4;n+)23 Console.WriteLine(string.Format(Do work in 0.,name);24 运行结果 4.2 跨 AppDomain 的线程 线程存在于进程当中,它在不同的时刻可以运行于多个不同的 AppDomain 当中。它是进程中的基本执行单元,在进程入口执行的第一

21、个线程被视为这个进程的主线程。在.NET应用程序中,都是以 Main()方法作为入口的,当调用此方法时 系统就会自动创建一个主线程。线程主要是由 CPU寄存器、调用栈和线程本地存储器(Thread Local Storage,TLS)组成的。CPU 寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS 主要用于存放线程的状态信息。关于线程的介绍,可参考“C#综合揭秘细说多线程(上)”、“C#综合揭秘细说多线程(下)”下面的例子将介绍一下如何跨 AppDomain 使用线程,首先建立一个ConsoleApplication 项目,在执行时输入当前线程及应用程序域

22、的信息,最后生成Example.exe的可执行程序。1staticvoid Main(string args)2 3var message=string.Format(CurrentThreadID is:0tAppDomainID is:1,4 Thread.CurrentThread.ManagedThreadId,AppDomain.CurrentDomain.Id);5 Console.WriteLine(message);6 Console.Read();7 然后再新建一个 ConsoleApplication 项目,在此项目中新一个 AppDomain 对象,在新的 AppDoma

23、in中通过 ExecuteAssembly方法执行 Example.exe程序。1staticvoid Main(string args)2 3/当前应用程序域信息 4 Console.WriteLine(CurrentAppDomain start!);5 ShowMessage();6 7/建立新的应用程序域对象 8 AppDomain newAppDomain=AppDomain.CreateDomain(newAppDomain);9/在新的应用程序域中执行 Example.exe 10 newAppDomain.ExecuteAssembly(Example.exe);11 12 A

24、ppDomain.Unload(newAppDomain);13 Console.ReadKey();14 15 16publicstaticvoid ShowMessage()17 18var message=string.Format(CurrentThreadID is:0tAppDomainID is:1,19 Thread.CurrentThread.ManagedThreadId,AppDomain.CurrentDomain.Id);20 Console.WriteLine(message);21 运行结果 可见,ID等于 9的线程在不同时间内分别运行于 AppDomain 1与

25、 AppDomain 2 当中。4.3 跨上下文的线程 线程既然能够跨越 AppDomain的边界,当然也能跨越不同的上下文。下面这个例子中,线程将同时运行在默认上下文与提供安全线程的上下文中。1class Program 2 3 Synchronization 4publicclass ContextBound:ContextBoundObject 5 6publicvoid Test()7 8 ShowMessage();9 10 11 12staticvoid Main(string args)13 14/当前应用程序域信息 15 Console.WriteLine(CurrentApp

26、Domain start!);16 ShowMessage();17 18/在上下文绑定对象中运行线程 19 ContextBound contextBound=new ContextBound();20 contextBound.Test();21 Console.ReadKey();22 23 24publicstaticvoid ShowMessage()25 26var message=string.Format(CurrentThreadID is:0tContextID is:1,27 Thread.CurrentThread.ManagedThreadId,Thread.Curr

27、entContext.ContextID);28 Console.WriteLine(message);29 30 运行结果 本篇总结 进程(Process)、线程(Thread)、应用程序域(AppDomain)、上下文(Context)的关系如图 5.0,一个进程内可以包括多个应用程序域,也有包括多个线程,线程也可以穿梭于多个应用程序域当中。但在同一个时刻,线程只会处于一个应用程序域内。线程也能穿梭于多个上下文当中,进行对象的调用。虽然进程、应用程序域与上下文在平常的开发中并非经常用到,但深入地了解三者的关系,熟悉其操作方式对合理利用系统的资源,提高系统的效率是非常有意义的。尤其是三者与线程之间的关系尤为重要,特别是在一个多线程系统中,如果不能理清其关系而盲目使用多线程,容易造成资源抢占与死锁之类的错误。图 5.0 希望本篇文章对相关的开发人员有所帮助。

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1