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

上传人:b****6 文档编号:7115945 上传时间:2023-01-19 格式:DOCX 页数:15 大小:473.98KB
下载 相关 举报
C#综合细说进程应用程序域与上下文.docx_第1页
第1页 / 共15页
C#综合细说进程应用程序域与上下文.docx_第2页
第2页 / 共15页
C#综合细说进程应用程序域与上下文.docx_第3页
第3页 / 共15页
C#综合细说进程应用程序域与上下文.docx_第4页
第4页 / 共15页
C#综合细说进程应用程序域与上下文.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

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

《C#综合细说进程应用程序域与上下文.docx》由会员分享,可在线阅读,更多相关《C#综合细说进程应用程序域与上下文.docx(15页珍藏版)》请在冰豆网上搜索。

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

C#综合细说进程应用程序域与上下文综合细说进程应用程序域与上下文引言本文主要是介绍进程(Process)、应用程序域(AppDomain)、.NET上下文(Context)的概念与操作。

虽然在一般的开发当中这三者并不常用,但熟悉三者的关系,深入了解其作用,对提高系统的性能有莫大的帮助。

在本篇最后的一节当中将会介绍到三者与线程之间的关系,希望对多线程开发人员能提供一定的帮助。

因为时间仓促,文中有错误的地方敬请点评。

目录一、进程的概念与作用二、应用程序域三、深入了解.NET上下文四、进程应用程序域与线程的关系一、进程的概念与作用进程(Process)是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。

进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式),一个进程运行的失败也不会影响其他进程的运行,Windows系统就是利用进程把工作划分为多个独立的区域的。

进程可以理解为一个程序的基本边界。

1.1Process的属性与方法在System.Diagnostics命名空间当中存在Process类,专门用于管理进程的开始、结束,访问进程中的模块,获取进程中的线程,设定进程的优先级别等功能。

表1.0显示了Process类的常用属性:

属性说明BasePriority获取关联进程的基本优先级。

ExitCode获取关联进程终止时指定的值。

ExitTime获取关联进程退出的时间。

Handle返回关联进程的本机句柄。

HandleCount获取由进程打开的句柄数。

HasExited获取指示关联进程是否已终止的值。

Id获取关联进程的唯一标识符。

MachineName获取关联进程正在其上运行的计算机的名称。

MainModule获取关联进程的主模块。

Modules获取已由关联进程加载的模块。

PriorityClass获取或设置关联进程的总体优先级类别。

ProcessName获取该进程的名称。

StartInfo获取或设置要传递给Process的Start方法的属性。

StartTime获取关联进程启动的时间。

SynchronizingObject获取或设置用于封送由于进程退出事件而发出的事件处理程序调用的对象。

Threads获取在关联进程中运行的一组线程表1.0除了上述属性,Process类也定义了下列经常使用的方法:

方法说明GetProcessById创建新的Process组件,并将其与您指定的现有进程资源关联。

GetProcessByName创建多个新的Process组件,并将其与您指定的现有进程资源关联。

GetCurrentProcess获取新的Process组件并将其与当前活动的进程关联。

GetProcesses获取本地计算机上正在运行的每一个进程列表。

Start启动一个进程。

Kill立即停止关联的进程。

Close释放与此组件关联的所有资源。

WaitForExit指示Process组件无限期地等待关联进程退出。

表1.1Process类的详细信息可以参考http:

/下面将举例详细介绍一下Process的使用方式1.2建立与销毁进程利用Start()与Kill()方法可以简单建立或者销毁进程,下面例子就是利用Start方法启动记事本的进程,并打开File.txt文件。

2秒钟以后,再使用Kill方法销毁进程,并关闭记事本。

1staticvoidMain(stringargs)23Processprocess=Process.Start(notepad.exe,File.txt);4Thread.Sleep(2000);5process.Kill();61.3列举计算机运行中的进程在表1.0中可以看到,使用GetProcesses方法可以获取本地计算机上正在运行的每一个进程列表。

而进程的Id属性是每个进程的唯一标志,通过下面的方法,可以显示当前计算机运行的所有进程信息。

因为篇幅关系,下面例子只获取前10个进程。

1staticvoidMain(stringargs)23varprocessList=Process.GetProcesses()4.OrderBy(x=x.Id)5.Take(10);6foreach(varprocessinprocessList)7Console.WriteLine(string.Format(ProcessIdis:

0tProcessNameis:

1,8process.Id,process.ProcessName);9Console.ReadKey();10运行结果如果已知进程的Id,就可以通过GetProcessById方法获取对应的进程。

1staticvoidMain(stringargs)23try45varprocess=Process.GetProcessById(1772);6Console.WriteLine(Processnameis:

+process.ProcessName);78catch(ArgumentExceptionex)910Console.WriteLine(Processisnothing!

);1112Console.ReadKey();13同样地,你也可能通过GetProcessByName方法获取多个对应名称的进程。

注意:

如果不能找到当前ID的进程,系统就会抛出ArgumentException异常。

所以使用方法GetProcessById获取进程时应该包含在try.catch.之内。

1.4获取进程中的多个模块在表1.0中包含了Modules属性,通过此属性可能获取进程中的多个模块。

这些模块可以是以*.dll结尾的程序集,也可以是*.exe结尾的可执行程序。

下面的例子就是通过Process的GetCurrentProcess方法获取当前运行的进程信息,然后显示当前进程的多个模块信息。

1staticvoidMain(stringargs)23varmoduleList=Process.GetCurrentProcess().Modules;4foreach(System.Diagnostics.ProcessModulemoduleinmoduleList)5Console.WriteLine(string.Format(0nURL:

1nVersion:

2,6module.ModuleName,module.FileName,module.FileVersionInfo.FileVersion);7Console.ReadKey();8运行结果:

回到目录二、应用程序域使用.NET建立的可执行程序*.exe,并没有直接承载在进程当中,而是承载到应用程序域(AppDomain)当中。

应用程序域是.NET引入的一个新概念,它比进程所占用的资源要少,可以被看作是一个轻量级的进程。

在一个进程中可以包含多个应用程序域,一个应用程序域可以装载一个可执行程序(*.exe)或者多个程序集(*.dll)。

这样可以使应用程序域之间实现深度隔离,即使进程中的某个应用程序域出现错误,也不会影响其他应用程序域的正常运作。

当一个程序集同时被多个应用程序域调用时,会出现两种情况:

第一种情况:

CLR分别为不同的应用程序域加载此程序集。

第二种情况:

CLR把此程序集加载到所有的应用程序域之外,并实现程序集共享,此情况比较特殊,被称作为DomainNeutral。

2.1AppDomain的属性与方法在System命名空间当中就存在AppDomain类,用管理应用程序域。

下面是AppDomain类的常用属性:

属性说明ActivationContext获取当前应用程序域的激活上下文。

ApplicationIdentity获得应用程序域中的应用程序标识。

BaseDirectory获取基目录。

CurrentDomain获取当前Thread的当前应用程序域。

Id获得一个整数,该整数唯一标识进程中的应用程序域。

RelativeSearchPath获取相对于基目录的路径,在此程序集冲突解决程序应探测专用程序集。

SetupInformation获取此实例的应用程序域配置信息。

表2.0AppDomain类中有多个方法,可以用于创建一个新的应用程序域,或者执行应用程序域中的应用程序。

方法说明CreateDomain创建新的应用程序域。

CreateInstance创建在指定程序集中定义的指定类型的新实例。

CreateInstanceFrom创建在指定程序集文件中定义的指定类型的新实例。

DoCallBack在另一个应用程序域中执行代码,该应用程序域由指定的委托标识。

ExecuteAssembly执行指定文件中包含的程序集。

ExecuteAssemblyByName执行程序集。

GetAssemblies获取已加载到此应用程序域的执行上下文中的程序集。

GetCurrentThreadId获取当前线程标识符。

GetData为指定名称获取存储在当前应用程序域中的值。

IsDefaultAppDomain返回一个值,指示应用程序域是否是进程的默认应用程序域。

SetData为应用程序域属性分配值。

Load将Assembly加载到此应用程序域中。

Unload卸载指定的应用程序域。

表2.1AppDomain类中有多个事件,用于管理应用程序域生命周期中的不同部分。

事件说明AssemblyLoad在加载程序集时发生。

AssemblyResolve在对程序集的解析失败时发生。

DomainUnload在即将卸载AppDomain时发生。

ProcessExit当默认应用程序域的父进程存在时发生。

ReflectionOnlyAssemblyResolve当程序集的解析在只反射上下文中失败时发生。

ResourceResolve当资源解析因资源不是程序集中的有效链接资源或嵌入资源而失败时发生。

TypeResolve在对类型的解析失败时发生。

UnhandledException当某个异常未被捕获时出现。

表2.2下面将举例详细介绍一下AppDomain的使用方式2.2在AppDomain中加载程序集由表2.1中可以看到,通过CreateDomain方法可以建立一个新的应用程序域。

下面的例子将使用CreateDomain建立一个应用程序域,并使用Load方法加载程序集Model.dll。

最后使用GetAssemblies方法,列举此应用程序域中的所有程序集。

1staticvoidMain(stringargs)23varappDomain=AppDomain.CreateDomain(NewAppDomain);4appDomain.Load(Model);5foreach(varassemblyinappDomain.GetAssemblies()6Console.WriteLine(string.Format(0n-,7assembly.FullName);8Console.ReadKey();9运行结果注意:

当加载程序集后,就无法把它从AppDomain中卸载,只能把整个AppDomain卸载。

当需要在AppDomain加载可执行程序时,可以使用ExecuteAssembly方法。

AppDomain.ExecuteAssembly(Example.exe);2.3卸载AppDomain通过Unload可以卸载AppDomain,在AppDomain卸载时将会触发DomainUnload事件。

下面的例子中,将会使用CreateDomain建立一个名为NewAppDomain的应用程序域。

然后建立AssemblyLoad的事件处理方法,在程序集加载时显示程序集的信息。

最后建立DomainUnload事件处理方法,在AppDomain卸载时显示卸载信息。

1staticvoidMain(stringargs)23/新建名为NewAppDomain的应用程序域4AppDomainnewAppDomain=AppDomain.CreateDomain(NewAppDomain);5/建立AssemblyLoad事件处理方法6newAppDomain.AssemblyLoad+=7(obj,e)=89Console.WriteLine(string.Format(0isloading!

e.LoadedAssembly.GetName();10;11/建立DomainUnload事件处理方法12newAppDomain.DomainUnload+=13(obj,e)=1415Console.WriteLine(NewAppDomainUnload!

);16;17/加载程序集18newAppDomain.Load(Model);19/模拟操作20for(intn=0;n1011Console.WriteLine(NewAppDomainunload!

);12;13/调用委托14newAppDomain.DoCallBack(crossAppDomainDelegate);15AppDomain.Unload(newAppDomain);16Console.ReadKey();171819staticpublicvoidMyCallBack()2021stringname=AppDomain.CurrentDomain.FriendlyName;22for(intn=0;n4;n+)23Console.WriteLine(string.Format(Doworkin0.,name);24运行结果4.2跨AppDomain的线程线程存在于进程当中,它在不同的时刻可以运行于多个不同的AppDomain当中。

它是进程中的基本执行单元,在进程入口执行的第一个线程被视为这个进程的主线程。

在.NET应用程序中,都是以Main()方法作为入口的,当调用此方法时系统就会自动创建一个主线程。

线程主要是由CPU寄存器、调用栈和线程本地存储器(ThreadLocalStorage,TLS)组成的。

CPU寄存器主要记录当前所执行线程的状态,调用栈主要用于维护线程所调用到的内存与数据,TLS主要用于存放线程的状态信息。

关于线程的介绍,可参考“C#综合揭秘细说多线程(上)”、“C#综合揭秘细说多线程(下)”下面的例子将介绍一下如何跨AppDomain使用线程,首先建立一个ConsoleApplication项目,在执行时输入当前线程及应用程序域的信息,最后生成Example.exe的可执行程序。

1staticvoidMain(stringargs)23varmessage=string.Format(CurrentThreadIDis:

0tAppDomainIDis:

1,4Thread.CurrentThread.ManagedThreadId,AppDomain.CurrentDomain.Id);5Console.WriteLine(message);6Console.Read();7然后再新建一个ConsoleApplication项目,在此项目中新一个AppDomain对象,在新的AppDomain中通过ExecuteAssembly方法执行Example.exe程序。

1staticvoidMain(stringargs)23/当前应用程序域信息4Console.WriteLine(CurrentAppDomainstart!

);5ShowMessage();67/建立新的应用程序域对象8AppDomainnewAppDomain=AppDomain.CreateDomain(newAppDomain);9/在新的应用程序域中执行Example.exe10newAppDomain.ExecuteAssembly(Example.exe);1112AppDomain.Unload(newAppDomain);13Console.ReadKey();141516publicstaticvoidShowMessage()1718varmessage=string.Format(CurrentThreadIDis:

0tAppDomainIDis:

1,19Thread.CurrentThread.ManagedThreadId,AppDomain.CurrentDomain.Id);20Console.WriteLine(message);21运行结果可见,ID等于9的线程在不同时间内分别运行于AppDomain1与AppDomain2当中。

4.3跨上下文的线程线程既然能够跨越AppDomain的边界,当然也能跨越不同的上下文。

下面这个例子中,线程将同时运行在默认上下文与提供安全线程的上下文中。

1classProgram23Synchronization4publicclassContextBound:

ContextBoundObject56publicvoidTest()78ShowMessage();9101112staticvoidMain(stringargs)1314/当前应用程序域信息15Console.WriteLine(CurrentAppDomainstart!

);16ShowMessage();1718/在上下文绑定对象中运行线程19ContextBoundcontextBound=newContextBound();20contextBound.Test();21Console.ReadKey();222324publicstaticvoidShowMessage()2526varmessage=string.Format(CurrentThreadIDis:

0tContextIDis:

1,27Thread.CurrentThread.ManagedThreadId,Thread.CurrentContext.ContextID);28Console.WriteLine(message);2930运行结果本篇总结进程(Process)、线程(Thread)、应用程序域(AppDomain)、上下文(Context)的关系如图5.0,一个进程内可以包括多个应用程序域,也有包括多个线程,线程也可以穿梭于多个应用程序域当中。

但在同一个时刻,线程只会处于一个应用程序域内。

线程也能穿梭于多个上下文当中,进行对象的调用。

虽然进程、应用程序域与上下文在平常的开发中并非经常用到,但深入地了解三者的关系,熟悉其操作方式对合理利用系统的资源,提高系统的效率是非常有意义的。

尤其是三者与线程之间的关系尤为重要,特别是在一个多线程系统中,如果不能理清其关系而盲目使用多线程,容易造成资源抢占与死锁之类的错误。

图5.0希望本篇文章对相关的开发人员有所帮助。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 工作范文 > 行政公文

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

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