( 2)对服务
![](/icons/64466de.gif)
深入讨论的上
上
![](/icons/64466yi.gif)
章其实只是概括性
![](/icons/64466de.gif)
介绍
![](/icons/64466dou.gif)
下面开始才是真正
![](/icons/64466de.gif)
细节所在
![](/icons/64466dou2.gif)
在进入点
![](/icons/64466hanshu.gif)
里面要完成ServiceMain
![](/icons/64466de.gif)
![](/icons/64466chushi.gif)
化
![](/icons/64466dou.gif)
准确点说是
![](/icons/64466chushi.gif)
化
![](/icons/64466yi.gif)
个SERVICE_TABLE_ENTRY结构
![](/icons/64466shuzu.gif)
![](/icons/64466dou.gif)
这个结构记录了这个服务
![](/icons/64466chengxu.gif)
里面所包含
![](/icons/64466de.gif)
所有服务
![](/icons/64466de.gif)
名称和服务
![](/icons/64466de.gif)
进入点
![](/icons/64466hanshu.gif)
![](/icons/64466dou.gif)
下面是
![](/icons/64466yi.gif)
个SERVICE_TABLE_ENTRY
![](/icons/64466de.gif)
例子:
SERVICE_TABLE_ENTRY service_table_entry
![](/icons/64466zhk2.gif)
=
{
{ \"MyFTPd\" , FtpdMain },
{ \"MyHttpd\", Httpserv},
{ NULL, NULL },
};
第
![](/icons/64466yi.gif)
个成员代表服务
![](/icons/64466de.gif)
名字
![](/icons/64466dou.gif)
第 2个成员是ServiceMain回调
![](/icons/64466hanshu.gif)
![](/icons/64466de.gif)
地址
![](/icons/64466dou.gif)
上面
![](/icons/64466de.gif)
服务
![](/icons/64466chengxu.gif)
![](/icons/64466yinwei.gif)
拥有两个服务
![](/icons/64466dou.gif)
所以有 3个SERVICE_TABLE_ENTRY元素
![](/icons/64466dou.gif)
前两个用于服务
![](/icons/64466dou.gif)
最后
![](/icons/64466de.gif)
NULL指明
![](/icons/64466shuzu.gif)
![](/icons/64466de.gif)
结束
![](/icons/64466dou2.gif)
接下来这个
![](/icons/64466shuzu.gif)
![](/icons/64466de.gif)
地址被传递到StartServiceCtrlDispatcher
![](/icons/64466hanshu.gif)
:
BOOL StartServiceCtrlDispatcher(
LPSERVICE_TABLE_ENTRY lpServiceStartTable
)
这个Win32
![](/icons/64466hanshu.gif)
表明可执行文件
![](/icons/64466de.gif)
进程怎样通知SCM包含在这个进程中
![](/icons/64466de.gif)
服务
![](/icons/64466dou2.gif)
就像上
![](/icons/64466yi.gif)
章中讲
![](/icons/64466de.gif)
那样
![](/icons/64466dou.gif)
StartServiceCtrlDispatcher为每
![](/icons/64466yi.gif)
个传递到它
![](/icons/64466de.gif)
![](/icons/64466shuzu.gif)
中
![](/icons/64466de.gif)
非空元素产生
![](/icons/64466yi.gif)
个新
![](/icons/64466de.gif)
线程
![](/icons/64466dou.gif)
每
![](/icons/64466yi.gif)
个进程开始执行由
![](/icons/64466shuzu.gif)
元素中
![](/icons/64466de.gif)
lpServiceStartTable指明
![](/icons/64466de.gif)
ServiceMain
![](/icons/64466hanshu.gif)
![](/icons/64466dou2.gif)
SCM启动
![](/icons/64466yi.gif)
个服务
![](/icons/64466chengxu.gif)
的后
![](/icons/64466dou.gif)
它会等待该
![](/icons/64466chengxu.gif)
![](/icons/64466de.gif)
主线程去调StartServiceCtrlDispatcher
![](/icons/64466dou2.gif)
如果那个
![](/icons/64466hanshu.gif)
在两分钟内没有被
![](/icons/64466diaoyong.gif)
![](/icons/64466dou.gif)
SCM将会认为这个服务有问题
![](/icons/64466dou.gif)
并
![](/icons/64466diaoyong.gif)
TerminateProcess去杀死这个进程
![](/icons/64466dou2.gif)
这就要求你
![](/icons/64466de.gif)
主线程要尽可能快
![](/icons/64466de.gif)
![](/icons/64466diaoyong.gif)
StartServiceCtrlDispatcher
![](/icons/64466dou2.gif)
StartServiceCtrlDispatcher
![](/icons/64466hanshu.gif)
则并不立即返回
![](/icons/64466dou.gif)
相反它会驻留在
![](/icons/64466yi.gif)
个循环内
![](/icons/64466dou2.gif)
当在该循环内时
![](/icons/64466dou.gif)
StartServiceCtrlDispatcher悬挂起自己
![](/icons/64466dou.gif)
等待下面两个事件中
![](/icons/64466de.gif)
![](/icons/64466yi.gif)
个发生
![](/icons/64466dou2.gif)
第
![](/icons/64466yi.gif)
![](/icons/64466dou.gif)
如果SCM要去送
![](/icons/64466yi.gif)
个控制通知给运行在这个进程内
![](/icons/64466yi.gif)
个服务
![](/icons/64466de.gif)
时候
![](/icons/64466dou.gif)
这个线程就会激活
![](/icons/64466dou2.gif)
当控制通知到达后
![](/icons/64466dou.gif)
线程激活并
![](/icons/64466diaoyong.gif)
相应服务
![](/icons/64466de.gif)
CtrlHandler
![](/icons/64466hanshu.gif)
![](/icons/64466dou2.gif)
CtrlHandler
![](/icons/64466hanshu.gif)
处理这个服务控制通知
![](/icons/64466dou.gif)
并返回到StartServiceCtrlDispatcher
![](/icons/64466dou2.gif)
StartServiceCtrlDispatcher循环回去后再
![](/icons/64466yi.gif)
次悬挂自己
![](/icons/64466dou2.gif)
第 2
![](/icons/64466dou.gif)
如果服务线程中
![](/icons/64466de.gif)
![](/icons/64466yi.gif)
个服务中止
![](/icons/64466dou.gif)
这个线程也将激活
![](/icons/64466dou2.gif)
在这种情况下
![](/icons/64466dou.gif)
该进程将运行在它里面
![](/icons/64466de.gif)
服务数减
![](/icons/64466yi.gif)
![](/icons/64466dou2.gif)
如果服务数为零
![](/icons/64466dou.gif)
StartServiceCtrlDispatcher就会返回到入口点
![](/icons/64466hanshu.gif)
![](/icons/64466dou.gif)
以便能够执行任何和进程有关
![](/icons/64466de.gif)
清除工作并结束进程
![](/icons/64466dou2.gif)
如果还有服务在运行
![](/icons/64466dou.gif)
哪怕只是
![](/icons/64466yi.gif)
个服务
![](/icons/64466dou.gif)
StartServiceCtrlDispatcher也会继续循环下去
![](/icons/64466dou.gif)
继续等待其它
![](/icons/64466de.gif)
控制通知或者剩下
![](/icons/64466de.gif)
服务线程中止
![](/icons/64466dou2.gif)
上面
![](/icons/64466de.gif)
内容是有关入口点
![](/icons/64466hanshu.gif)
![](/icons/64466de.gif)
![](/icons/64466dou.gif)
下面
![](/icons/64466de.gif)
内容则是有关ServiceMain
![](/icons/64466hanshu.gif)
![](/icons/64466de.gif)
![](/icons/64466dou2.gif)
还记得以前讲过
![](/icons/64466de.gif)
ServiceMain
![](/icons/64466hanshu.gif)
![](/icons/64466de.gif)
![](/icons/64466de.gif)
原型吗?但实际上
![](/icons/64466yi.gif)
个ServiceMain
![](/icons/64466hanshu.gif)
通常忽略传递给它
![](/icons/64466de.gif)
两个参数
![](/icons/64466dou.gif)
![](/icons/64466yinwei.gif)
服务
![](/icons/64466yi.gif)
般不如何传递参数
![](/icons/64466dou2.gif)
设置
![](/icons/64466yi.gif)
个服务最好
![](/icons/64466de.gif)
思路方法就是设置注册表
![](/icons/64466dou.gif)
![](/icons/64466yi.gif)
般服务在
HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Service\\ServiceName\\Parameters
子键下存放自己
![](/icons/64466de.gif)
设置
![](/icons/64466dou.gif)
这里
![](/icons/64466de.gif)
ServiceName是服务
![](/icons/64466de.gif)
名字
![](/icons/64466dou2.gif)
事实上
![](/icons/64466dou.gif)
可能要写
![](/icons/64466yi.gif)
个客户应用
![](/icons/64466chengxu.gif)
去进行服务
![](/icons/64466de.gif)
背景设置
![](/icons/64466dou.gif)
这个客户应用
![](/icons/64466chengxu.gif)
将这些信息存在注册表中
![](/icons/64466dou.gif)
以便服务读取
![](/icons/64466dou2.gif)
当
![](/icons/64466yi.gif)
个外部应用
![](/icons/64466chengxu.gif)
已经改变了某个正在运行中
![](/icons/64466de.gif)
服务
![](/icons/64466de.gif)
设置数据
![](/icons/64466de.gif)
时候
![](/icons/64466dou.gif)
这个服务能够用RegNot
![](/icons/64466if.gif)
yChangeKeyValue
![](/icons/64466hanshu.gif)
去接受
![](/icons/64466yi.gif)
个通知
![](/icons/64466dou.gif)
这样就允许服务快速
![](/icons/64466de.gif)
重新设置自己
![](/icons/64466dou2.gif)
前面讲到StartServiceCtrlDispatcher为每
![](/icons/64466yi.gif)
个传递到它
![](/icons/64466de.gif)
![](/icons/64466shuzu.gif)
中
![](/icons/64466de.gif)
非空元素产生
![](/icons/64466yi.gif)
个新
![](/icons/64466de.gif)
线程
![](/icons/64466dou2.gif)
接下来
![](/icons/64466dou.gif)
![](/icons/64466yi.gif)
个ServiceMain要做些什么呢?MSDN里面
![](/icons/64466de.gif)
原文是这样说
![](/icons/64466de.gif)
:The ServiceMain function should immediately call the RegisterServiceCtrlHandler function to spec
![](/icons/64466if.gif)
y a Handler function to handle control requests. Next, it should call the SetServiceStatus function to send status information to the service control manager. 为什么呢?
![](/icons/64466yinwei.gif)
发出启动服务请求的后
![](/icons/64466dou.gif)
如果在
![](/icons/64466yi.gif)
定时间的内无法完成服务
![](/icons/64466de.gif)
![](/icons/64466chushi.gif)
化
![](/icons/64466dou.gif)
SCM会认为服务
![](/icons/64466de.gif)
启动已经失败了
![](/icons/64466dou.gif)
这个时间
![](/icons/64466de.gif)
长度在Win NT 4.0中是80秒
![](/icons/64466dou.gif)
Win2000中不详...
基于上面
![](/icons/64466de.gif)
理由
![](/icons/64466dou.gif)
ServiceMain要迅速完成自身工作
![](/icons/64466dou.gif)
首先是必不可少
![](/icons/64466de.gif)
两项工作
![](/icons/64466dou.gif)
第
![](/icons/64466yi.gif)
项是
![](/icons/64466diaoyong.gif)
RegisterServiceCtrlHandler
![](/icons/64466hanshu.gif)
去通知SCM它
![](/icons/64466de.gif)
CtrlHandler回调
![](/icons/64466hanshu.gif)
![](/icons/64466de.gif)
地址:
SERVICE_STATUS_HANDLE RegisterServiceCtrlHandler(
LPCTSTR lpServiceName, //服务
![](/icons/64466de.gif)
名字
LPHANDLER_FUNCTION lpHandlerProc //CtrlHandler
![](/icons/64466hanshu.gif)
地址
)
第
![](/icons/64466yi.gif)
个参数指明你正在建立
![](/icons/64466de.gif)
CtrlHandler是为哪
![](/icons/64466yi.gif)
个服务所用
![](/icons/64466dou.gif)
第 2个参数是CtrlHandler
![](/icons/64466hanshu.gif)
![](/icons/64466de.gif)
地址
![](/icons/64466dou2.gif)
lpServiceName必须和在SERVICE_TABLE_ENTRY里面被
![](/icons/64466chushi.gif)
化
![](/icons/64466de.gif)
服务
![](/icons/64466de.gif)
名字相匹配
![](/icons/64466dou2.gif)
RegisterServiceCtrlHandler返回
![](/icons/64466yi.gif)
个SERVICE_STATUS_HANDLE
![](/icons/64466dou.gif)
这是
![](/icons/64466yi.gif)
个32位
![](/icons/64466de.gif)
句柄
![](/icons/64466dou2.gif)
SCM用它来唯
![](/icons/64466yi.gif)
确定这个服务
![](/icons/64466dou2.gif)
当这个服务需要把它当时
![](/icons/64466de.gif)
状态报告给SCM
![](/icons/64466de.gif)
时候
![](/icons/64466dou.gif)
就必须把这个句柄传给需要它
![](/icons/64466de.gif)
Win32
![](/icons/64466hanshu.gif)
![](/icons/64466dou2.gif)
注意:这个句柄和其他大多数
![](/icons/64466de.gif)
句柄区别
![](/icons/64466dou.gif)
你无需关闭它
![](/icons/64466dou2.gif)
SCM要求ServiceMain
![](/icons/64466hanshu.gif)
![](/icons/64466de.gif)
线程在
![](/icons/64466yi.gif)
秒钟内
![](/icons/64466diaoyong.gif)
RegisterServiceCtrlHandler
![](/icons/64466hanshu.gif)
![](/icons/64466dou.gif)
否则SCM会认为服务已经失败
![](/icons/64466dou2.gif)
但在这种情况下
![](/icons/64466dou.gif)
SCM不会终止服务
![](/icons/64466dou.gif)
不过在NT 4中将无法启动这个服务
![](/icons/64466dou.gif)
同时会返回
![](/icons/64466yi.gif)
个不正确
![](/icons/64466de.gif)
![](/icons/64466cuowu.gif)
信息
![](/icons/64466dou.gif)
这
![](/icons/64466yi.gif)
点在Windows 2000中得到了修正
![](/icons/64466dou2.gif)
在RegisterServiceCtrlHandler
![](/icons/64466hanshu.gif)
返回后
![](/icons/64466dou.gif)
ServiceMain线程要立即告诉SCM服务正在继续
![](/icons/64466chushi.gif)
化
![](/icons/64466dou2.gif)
具体
![](/icons/64466de.gif)
思路方法是通过
![](/icons/64466diaoyong.gif)
SetServiceStatus
![](/icons/64466hanshu.gif)
传递SERVICE_STATUS数据结构
![](/icons/64466dou2.gif)
BOOL SetServiceStatus(
SERVICE_STATUS_HANDLE hService, //服务
![](/icons/64466de.gif)
句柄
SERVICE_STATUS lpServiceStatus //SERVICE_STATUS结构
![](/icons/64466de.gif)
地址
)
这个
![](/icons/64466hanshu.gif)
要求传递给它指明服务
![](/icons/64466de.gif)
句柄(刚刚通过
![](/icons/64466diaoyong.gif)
RegisterServiceCtrlHandler得到)
![](/icons/64466dou.gif)
和
![](/icons/64466yi.gif)
个
![](/icons/64466chushi.gif)
化
![](/icons/64466de.gif)
SERVICE_STATUS结构
![](/icons/64466de.gif)
地址:
typedef struct _SERVICE_STATUS
{
DWORD dwServiceType;
DWORD dwCurrentState;
DWORD dwControlsAccepted;
DWORD dwWin32ExitCode;
DWORD dwServiceSpec
![](/icons/64466if.gif)
icExitCode;
DWORD dwCheckPo
![](/icons/64466int.gif)
;
DWORD dwWaitH
![](/icons/64466int.gif)
;
} SERVICE_STATUS, *LPSERVICE_STATUS;
SERVICE_STATUS结构含有 7个成员
![](/icons/64466dou.gif)
它们反映服务
![](/icons/64466de.gif)
现行状态
![](/icons/64466dou2.gif)
所有这些成员必须在这个结构被传递到SetServiceStatus的前正确
![](/icons/64466de.gif)
设置
成员dwServiceType指明服务可执行文件
![](/icons/64466de.gif)
类型
![](/icons/64466dou2.gif)
如果你
![](/icons/64466de.gif)
可执行文件中只有
![](/icons/64466yi.gif)
个单独
![](/icons/64466de.gif)
服务
![](/icons/64466dou.gif)
就把这个成员设置成SERVICE_WIN32_OWN_PROCESS;如果拥有多个服务
![](/icons/64466de.gif)
话
![](/icons/64466dou.gif)
就设置成SERVICE_WIN32_SHARE_PROCESS
![](/icons/64466dou2.gif)
除了这两个标志的外
![](/icons/64466dou.gif)
如果你
![](/icons/64466de.gif)
服务需要和桌面发生交互(当然不推荐这样做)
![](/icons/64466dou.gif)
就要用“OR”运算符附加上SERVICE_INTERACTIVE_PROCESS
![](/icons/64466dou2.gif)
这个成员
![](/icons/64466de.gif)
值在你
![](/icons/64466de.gif)
服务
![](/icons/64466de.gif)
生存期内绝对不应该改变
![](/icons/64466dou2.gif)
成员dwCurrentState是这个结构中最重要
![](/icons/64466de.gif)
成员
![](/icons/64466dou.gif)
它将告诉SCM你
![](/icons/64466de.gif)
服务
![](/icons/64466de.gif)
现行状态
![](/icons/64466dou2.gif)
为了报告服务仍在
![](/icons/64466chushi.gif)
化
![](/icons/64466dou.gif)
应该把这个成员设置成SERVICE_START_PENDING
![](/icons/64466dou2.gif)
在以后具体讲述CtrlHandler
![](/icons/64466hanshu.gif)
![](/icons/64466de.gif)
时候具体解释其它可能
![](/icons/64466de.gif)
值
![](/icons/64466dou2.gif)
成员dwControlsAccepted指明服务愿意接受什么样
![](/icons/64466de.gif)
控制通知
![](/icons/64466dou2.gif)
如果你允许
![](/icons/64466yi.gif)
个SCP去暂停/继续服务
![](/icons/64466dou.gif)
就把它设成SERVICE_ACCEPT_PAUSE_CONTINUE
![](/icons/64466dou2.gif)
很多服务不支持暂停或继续
![](/icons/64466dou.gif)
就必须自己决定在服务中它是否可用
![](/icons/64466dou2.gif)
如果你允许
![](/icons/64466yi.gif)
个SCP去停止服务
![](/icons/64466dou.gif)
就要设置它为SERVICE_ACCEPT_STOP
![](/icons/64466dou2.gif)
如果服务要在操作系统关闭
![](/icons/64466de.gif)
时候得到通知
![](/icons/64466dou.gif)
设置它为SERVICE_ACCEPT_SHUTDOWN可以收到预期
![](/icons/64466de.gif)
结果
![](/icons/64466dou2.gif)
这些标志可以用“OR”运算符组合
![](/icons/64466dou2.gif)
成员dwWin32ExitCode和dwServiceSpec
![](/icons/64466if.gif)
icExitCode是允许服务报告
![](/icons/64466cuowu.gif)
![](/icons/64466de.gif)
关键
![](/icons/64466dou.gif)
如果希望服务去报告
![](/icons/64466yi.gif)
个Win32
![](/icons/64466cuowu.gif)
代码(预定义在WinError.h中)
![](/icons/64466dou.gif)
它就设置dwWin32ExitCode为需要
![](/icons/64466de.gif)
代码
![](/icons/64466dou2.gif)
![](/icons/64466yi.gif)
个服务也可以报告它本身特有
![](/icons/64466de.gif)
、没有映射到
![](/icons/64466yi.gif)
个预定义
![](/icons/64466de.gif)
Win32
![](/icons/64466cuowu.gif)
代码中
![](/icons/64466de.gif)
![](/icons/64466cuowu.gif)
![](/icons/64466dou2.gif)
为了这
![](/icons/64466yi.gif)
点
![](/icons/64466dou.gif)
要把dwWin32ExitCode设置为ERROR_SERVICE_SPECIFIC_ERROR
![](/icons/64466dou.gif)
然后还要设置成员dwServiceSpec
![](/icons/64466if.gif)
icExitCode为服务特有
![](/icons/64466de.gif)
![](/icons/64466cuowu.gif)
代码
![](/icons/64466dou2.gif)
当服务运行正常
![](/icons/64466dou.gif)
没有
![](/icons/64466cuowu.gif)
可以报告
![](/icons/64466de.gif)
时候
![](/icons/64466dou.gif)
就设置成员dwWin32ExitCode为NO_ERROR
![](/icons/64466dou2.gif)
最后
![](/icons/64466de.gif)
两个成员dwCheckPo
![](/icons/64466int.gif)
和dwWaitH
![](/icons/64466int.gif)
是
![](/icons/64466yi.gif)
个服务用来报告它当前
![](/icons/64466de.gif)
事件进展情况
![](/icons/64466de.gif)
![](/icons/64466dou2.gif)
当成员dwCurrentState被设置成SERVICE_START_PENDING
![](/icons/64466de.gif)
时候
![](/icons/64466dou.gif)
应该把dwCheckPo
![](/icons/64466int.gif)
设成0
![](/icons/64466dou.gif)
dwWaitH
![](/icons/64466int.gif)
设成
![](/icons/64466yi.gif)
个经过多次尝试后确定比较合适
![](/icons/64466de.gif)
数
![](/icons/64466dou.gif)
这样服务才能高效运行
![](/icons/64466dou2.gif)
![](/icons/64466yi.gif)
旦服务被完全
![](/icons/64466chushi.gif)
化
![](/icons/64466dou.gif)
就应该重新
![](/icons/64466chushi.gif)
化SERVICE_STATUS结构
![](/icons/64466de.gif)
成员
![](/icons/64466dou.gif)
更改dwCurrentState为SERVICE_RUNNING
![](/icons/64466dou.gif)
然后把dwCheckPo
![](/icons/64466int.gif)
和dwWaitH
![](/icons/64466int.gif)
都改为0
![](/icons/64466dou2.gif)
dwCheckPo
![](/icons/64466int.gif)
成员
![](/icons/64466de.gif)
存在对用户是有益
![](/icons/64466de.gif)
![](/icons/64466dou.gif)
它允许
![](/icons/64466yi.gif)
个服务报告它处于进程
![](/icons/64466de.gif)
哪
![](/icons/64466yi.gif)
步
![](/icons/64466dou2.gif)
每
![](/icons/64466yi.gif)
次
![](/icons/64466diaoyong.gif)
SetServiceStatus时
![](/icons/64466dou.gif)
可以增加它到
![](/icons/64466yi.gif)
个能指明服务已经执行到哪
![](/icons/64466yi.gif)
步
![](/icons/64466de.gif)
数字
![](/icons/64466dou.gif)
它可以帮助用户决定多长时间报告
![](/icons/64466yi.gif)
次服务
![](/icons/64466de.gif)
进展情况
![](/icons/64466dou2.gif)
如果决定要报告服务
![](/icons/64466de.gif)
![](/icons/64466chushi.gif)
化进程
![](/icons/64466de.gif)
每
![](/icons/64466yi.gif)
步
![](/icons/64466dou.gif)
就应该设置dwWaitH
![](/icons/64466int.gif)
为你认为到达下
![](/icons/64466yi.gif)
步所需
![](/icons/64466de.gif)
毫秒数
![](/icons/64466dou.gif)
而不是服务完成它
![](/icons/64466de.gif)
进程所需
![](/icons/64466de.gif)
毫秒数
![](/icons/64466dou2.gif)
在服务
![](/icons/64466de.gif)
所有
![](/icons/64466chushi.gif)
化都完成的后
![](/icons/64466dou.gif)
服务
![](/icons/64466diaoyong.gif)
SetServiceStatus指明SERVICE_RUNNING
![](/icons/64466dou.gif)
在那
![](/icons/64466yi.gif)
刻服务已经开始运行
![](/icons/64466dou2.gif)
通常
![](/icons/64466yi.gif)
个服务是把自己放在
![](/icons/64466yi.gif)
个循环的中来运行
![](/icons/64466de.gif)
![](/icons/64466dou2.gif)
在循环
![](/icons/64466de.gif)
内部这个服务进程悬挂自己
![](/icons/64466dou.gif)
等待指明它下
![](/icons/64466yi.gif)
步是应该暂停、继续或停止的类
![](/icons/64466de.gif)
网络请求或通知
![](/icons/64466dou2.gif)
当
![](/icons/64466yi.gif)
个请求到达
![](/icons/64466de.gif)
时候
![](/icons/64466dou.gif)
服务线程激活并处理这个请求
![](/icons/64466dou.gif)
然后再循环回去等待下
![](/icons/64466yi.gif)
个请求/通知
![](/icons/64466dou2.gif)
如果
![](/icons/64466yi.gif)
个服务由于
![](/icons/64466yi.gif)
个通知而激活
![](/icons/64466dou.gif)
它会先处理这个通知
![](/icons/64466dou.gif)
除非这个服务得到
![](/icons/64466de.gif)
是停止或关闭
![](/icons/64466de.gif)
通知
![](/icons/64466dou2.gif)
如果真
![](/icons/64466de.gif)
是停止或关闭
![](/icons/64466de.gif)
通知
![](/icons/64466dou.gif)
服务线程将退出循环
![](/icons/64466dou.gif)
执行必要
![](/icons/64466de.gif)
清除操作
![](/icons/64466dou.gif)
然后从这个线程返回
![](/icons/64466dou2.gif)
当ServiceMain线程返回并中止时
![](/icons/64466dou.gif)
引起在StartServiceCtrlDispatcher内睡眠
![](/icons/64466de.gif)
线程激活
![](/icons/64466dou.gif)
并像在前面解释过
![](/icons/64466de.gif)
那样
![](/icons/64466dou.gif)
减少它运行
![](/icons/64466de.gif)
服务
![](/icons/64466de.gif)
计数