跳转到内容

.NET 开发基础/服务

来自 Wikibooks,开放世界的开放书籍


服务、线程和应用程序域


服务、线程和应用程序域

[编辑 | 编辑源代码]

考试目标: 在 .NET Framework 应用程序中实现服务进程、线程和应用程序域

术语服务在此指 Windows 服务。Windows 服务的基本定义是无需用户界面的长期运行进程。为什么您需要一个无需用户界面的长期运行进程?主要有两个原因

  • 执行不需要用户干预的维护任务。例如,备份软件会定期检查备份计划,并在需要时执行不同的备份任务。这不需要用户界面。
  • 响应来自其他进程或操作系统的请求。像 IIS(处理 Web 请求的 Windows 组件)这样的 http 服务器会接收来自客户端浏览器的 http 请求并生成对这些浏览器的响应(html 页面)。数据库进程是另一个很好的例子。同样,http 服务器不需要用户界面,因为与客户端的交互是由客户端浏览器组件管理的。

关于服务的考试目标非常基本,涉及到您在处理它们时遇到的第一个问题

  • 既然服务没有用户界面,那么谁会启动和停止它?答案是操作系统直接执行服务,但您必须 “注册” 您的服务,让系统知道它在哪里以及如何处理它(这是安装过程)
  • 具有用户界面的进程基本上等待来自用户的事件。在没有消息泵(在典型的在线应用程序中获取用户输入的技术)的情况下,服务是如何“工作”的?
  • 如果服务执行用户界面功能,它将 “挂起” 并等待一个不存在的用户。如何避免这种情况?

更重要、更复杂的設計問題不会由本考试涵盖,而会在企业开发考试中讨论。

多线程

[编辑 | 编辑源代码]


Clipboard

待办事项
.NET 中多线程支持的描述


应用程序域

[编辑 | 编辑源代码]


Clipboard

待办事项
CLI 中应用程序域的简短描述


类、接口和工具

[编辑 | 编辑源代码]

实现、安装和控制服务

[编辑 | 编辑源代码]

考试目标: 实现、安装和控制服务

(参考 System.ServiceProcess 命名空间)

从 ServiceBase 类继承 - MSDN

服务是一个长期运行的可执行文件。它不提供用户界面,也不需要任何用户登录到计算机。服务以 System 身份运行,但可以选择让它们在不同的用户帐户下运行。ServiceBase 类是服务的基类。创建新服务时必须从它派生。
几乎所有服务都会覆盖 ServiceBase 的 OnStart 和 OnStop 方法。

ServiceController 类和 ServiceControllerPermission 类

ServiceController 类 - MSDN
ServiceControllerPermission 类 - MSDN

ServiceInstaller 和 ServiceProcessInstaller 类

ServiceInstaller - MSDN
ServiceProcessInstaller 类 - MSDN

ServiceChangeDescription 结构和 ServiceChangeReason 枚举

SessionChangeDescription 结构 - MSDN
SessionChangeReason 枚举 - MSDN

开发多线程应用程序

[编辑 | 编辑源代码]

考试目标: 开发多线程 .NET Framework 应用程序

(参考 System.Threading 命名空间)

Thread 类 - MSDN

ThreadPool 类 - MSDN

ThreadStart 委托、ParameterizedThreadStart 委托和 SynchronizationContext 类

ThreadStart 委托 - MSDN
创建线程的最简单方法是实例化 Thread 类。Thread 构造函数接受一个委托参数。ThreadStart 委托指向包含您的逻辑的方法。例如
Thread t1 = new Thread (new ThreadStart(LengthyLogic));
public void LengthyLogic ()
{
  // Logic code
}
ParameterizedThreadStart 委托 - MSDN
启动线程时,有时您需要传入一些要处理的数据。.NET 2.0 提供了一个新的委托 ParameterizedThreadStart,它接受一个 object 类型的参数。该类有一个新的重载函数 Thread.Start。它允许您指定要传递到线程的值。这种方法很简单,但不是类型安全的。示例
Thread t1 = new Thread(new ParameterizedThreadStart(LengthyLogic));
// Use the overload of the Start method that has a parameter of type Object.
t1.Start(myData);
static void LengthyLogic(object data)
{
  // Logic code
}
SynchronizationContext 类 - MSDN
Code Project 中 SynchronizationContext 类的示例 [1]

Timeout 类、Timer 类、TimerCallback 委托、WaitCallback 委托、WaitHandle 类和 WaitOrTimerCallback 委托

Timeout 类 - MSDN
Timer 类 - MSDN
TimerCallback 委托 - MSDN
WaitCallback 委托 - MSDN
WaitHandle 类 - MSDN
WaitOrTimerCallback 委托 - MSDN

ThreadExceptionEventArgs 类和 ThreadExceptionEventHanlder 类

ThreadExceptionEventArgs 类 - MSDN
ThreadExceptionEventHandler 类 - MSDN

ThreadState 枚举和 ThreadPriority 枚举

ThreadState 枚举 - MSDN
ThreadPriority 枚举 - MSDN

ReaderWriterLock 类 - MSDN

AutoResetEvent 类和 ManualResetEvent 类

AutoResetEvent 类 - MSDN
ManualResetEvent 类 - MSDN

IAsyncResult 接口和 ICancelableAsyncResult 接口

(参考 System 命名空间)
IAsyncResult 接口 - MSDN
ICancelableAsyncResult 接口 - MSDN

EventWaitHandle 类、RegisterWaitHandle 类、SendOrPostCallback 委托和 IOCompletionCallback 委托

EventWaitHandle 类 - MSDN
RegisterWaitHandle 类 - MSDN
这是考试目标和培训教材中的一个笔误。术语 **RegisterWaitForSingleObject** 应改为 saerch(参见 KB
SendOrPostCallback 委托 - MSDN
IOCompletionCallback 委托 - MSDN

Interlocked 类、NativeOverlapped 结构和 Overlapped 类

Interlocked 类 - MSDN
NativeOverlapped 结构 - MSDN
Overlapped 类 - MSDN

ExecutionContext 类、HostExecutionContext 类、HostExecutionContext 管理器和 ContextCallback 委托

ExecutionContext 类 - MSDN
HostExecutionContext 类 - MSDN
HostExecutionContext 管理器 - MSDN
实际上这里指的是 HostExecutionContextManager 类
ContextCallback 委托 - MSDN

LockCookie 结构、Monitor 类、Mutex 类和 Semaphore 类 MSDN]

LockCookie 结构 - MSDN
Monitor 类 - MSDN
Mutex 类 - MSDN
Semaphore 类 - MSDN
锁 vs Monitor vs Mutex - MSDN

使用应用程序域

[edit | edit source]

考试目标:使用应用程序域,在 .NET Framework 应用程序中创建通用语言运行时的隔离单元

(参考 System 命名空间)

创建应用程序域
[edit | edit source]

参见 MSDN

应用程序域是将一个进程划分为多个部分。在不同应用程序域中运行的应用程序与在不同进程中运行的应用程序一样隔离。因此它们无法访问另一个应用程序域中的内存。但是,如果运行的是本机代码,它可以无限地访问整个进程,包括其他应用程序域。

应用程序域更容易维护,速度也更快,因为在应用程序域之间通信比在进程之间通信更容易。一个应用程序域可以包含多个程序集。

要创建应用程序域,您至少需要提供新应用程序域的名称

 AppDomain ad = AppDomain.CreateDomain("Name");

使用 AppDomain.CurrentDomain 获取调用线程正在使用的应用程序域。

将程序集加载到应用程序域
[edit | edit source]

参见 MSDN

可以使用 AppDomain.ExecuteAssemblyByName 按名称执行程序集

 AppDomain ad = AppDomain.CreateDomain("Name");
 ad.ExecuteAssemblyByName("aname, Version=1.0.0.0, Culture=neutral, PublicKeyToken=a9b8c7d6");

或者使用 AppDomain.ExecuteAssembly 提供程序集的路径

 AppDomain ad = AppDomain.CreateDomain("Name");
 ad.ExecuteAssembly(@"c:\path\to\file.exe");
卸载应用程序域
[edit | edit source]

参见 MSDN

无法从默认应用程序域卸载程序集。但是,如果在不同的应用程序域中加载程序集,则可以卸载整个应用程序域,其中包括该应用程序域中的所有程序集。

要卸载应用程序域,请使用静态 AppDomain.Unload 函数

 AppDomain ad = AppDomain.CreateDomain("Name");
 AppDomain.Unload(ad);  
配置应用程序域
[edit | edit source]

参见 MSDN

修改应用程序域配置的最可能原因是限制某些权限,以限制攻击者利用程序集中的漏洞造成的损害。

例如,在 Internet Zone 中运行程序集。Internet Zone 具有有限的权限。要做到这一点,请创建一个 Zone Evidence 并将其作为参数提供给创建应用程序域时。

 object [] myEvidenceTypes = {new Zone (SecurityZone.Internet)};
 Evidence myEvidence = new  Evidence(myEvidenceTypes, null);
 AppDomain ad = AppDomain.CreateDomain("Name", myEvidence); // Pass the Evidence when creating the App. Domain
 ad.ExecuteAssembly(@"c:\path\to\file.exe");
 

还可以使用不同的权限在一个应用程序域中仅执行一个程序集;

 object [] myEvidenceTypes = {new Zone (SecurityZone.Internet)};
 Evidence myEvidence = new  Evidence(myEvidenceTypes, null);
 AppDomain ad = AppDomain.CreateDomain("Name");
 ad.ExecuteAssembly(@"c:\path\to\file.exe", myEvidence); // Pass the Evidence in the ExecuteAssembly function

除了 Evidence 之外,还可以使用 AppDomainSetup 类来设置其他属性。

 AppDomainSetup ads = new AppDomainSetup();
 ads.ApplicationBase = @"c:\Test";
 ads.DisallowCodeDownload = true;
 AppDomain ad = AppDomain.CreateDomain("Name", null, ads); // use null as second parameter for default Evidence
从应用程序域检索设置信息
[edit | edit source]

参见 MSDN

使用 AppDomain 的 SetupInformation 属性来读取该应用程序域中的设置;

 AppDomainSetup ads = AppDomain.CurrentDomain.SetupInformation;
 Console.WriteLine(ads.ConfigurationFile);
 Console.WriteLine(ads.ApplicationName);


上页 / 下页

华夏公益教科书