首页 > 代码库 > ServiceBase 类

ServiceBase 类

 

将作为一个服务应用程序的一部分存在的服务提供基类。 ServiceBase 必须派生自创建新的服务类时。

命名空间:   System.ServiceProcess
程序集:  System.ServiceProcess(位于 System.ServiceProcess.dll)

继承层次结构
 
 
System.Object
  System.MarshalByRefObject
    System.ComponentModel.Component
      System.ServiceProcess.ServiceBase

语法
 
 
C#
C++
F#
VB
 
public class ServiceBase : Component
构造函数
 
 
 名称说明
技术分享ServiceBase()

创建 ServiceBase 类的新实例。

属性
 
 
 名称说明
技术分享AutoLog

指示是否报表在事件日志中的启动、 停止、 暂停和继续命令。

技术分享CanHandlePowerEvent

获取或设置一个值,该值指示服务是否可以处理计算机电源状态更改的通知。

技术分享CanHandleSessionChangeEvent

获取或设置一个值,指示服务是否可以处理会话从终端服务器会话接收到的更改事件。

技术分享CanPauseAndContinue

获取或设置一个值,该值指示是否可以暂停和恢复该服务。

技术分享CanRaiseEvents

获取一个值,该值指示组件是否可以引发一个事件。(继承自 Component。)

技术分享CanShutdown

获取或设置一个值,该值在系统关闭时是否应通知服务。

技术分享CanStop

获取或设置一个值,指示它启动后是否可以停止服务。

技术分享Container

获取 IContainer ,其中包含 Component。(继承自 Component。)

技术分享DesignMode

获取一个值,该值指示是否 Component 当前处于设计模式。(继承自 Component。)

技术分享EventLog

获取可用于写入应用程序事件日志服务命令调用,如启动和停止通知事件日志。

技术分享Events

获取的事件处理程序附加到此列表 Component。(继承自 Component。)

技术分享ExitCode

获取或设置该服务的退出代码。

技术分享ServiceHandle

获取服务的服务控制句柄。

技术分享ServiceName

获取或设置用于标识服务对系统的短名称。

技术分享Site

获取或设置 ISite 的 Component。(继承自 Component。)

方法
 
 
 名称说明
技术分享CreateObjRef(Type)

创建包含所有生成代理用于与远程对象进行通信所需的相关信息的对象。(继承自 MarshalByRefObject。)

技术分享Dispose()

释放由 Component 使用的所有资源。(继承自 Component。)

技术分享Dispose(Boolean)

处置由 ServiceBase 占用的资源(内存除外)。(覆盖 Component.Dispose(Boolean)。)

技术分享Equals(Object)

确定指定的对象是否等于当前对象。(继承自 Object。)

技术分享Finalize()

在通过垃圾回收将 Component 回收之前,释放非托管资源并执行其他清理操作。(继承自 Component。)

技术分享GetHashCode()

作为默认哈希函数。(继承自 Object。)

技术分享GetLifetimeService()

检索当前生存期服务对象,用于控制此实例的生存期策略。(继承自 MarshalByRefObject。)

技术分享GetService(Type)

返回一个对象,该对象表示由 Component 或它的 Container 提供的服务。(继承自 Component。)

技术分享GetType()

获取当前实例的 Type。(继承自 Object。)

技术分享InitializeLifetimeService()

获取生存期服务对象来控制此实例的生存期策略。(继承自 MarshalByRefObject。)

技术分享MemberwiseClone()

创建当前 Object 的浅表副本。(继承自 Object。)

技术分享MemberwiseClone(Boolean)

创建当前的浅表副本MarshalByRefObject对象。(继承自 MarshalByRefObject。)

技术分享OnContinue()

在派生类中实现时 OnContinue 时继续命令发送到服务的服务控制管理器 (SCM) 运行。 指定当某个服务后继续正常工作正在暂停时要执行的操作。

技术分享OnCustomCommand(Int32)

在派生类中实现时 OnCustomCommand 服务控制管理器 (SCM) 向服务传递自定义命令时执行。 指定具有指定的参数值的命令发生时要采取的操作。

技术分享OnPause()

派生类中实现时,暂停命令发送到服务的服务控制管理器 (SCM) 时执行。 指定当服务就会暂停时要执行的操作。

技术分享OnPowerEvent(PowerBroadcastStatus)

派生类中实现时,在计算机的电源状态已发生更改时执行。 这适用于便携式计算机,当他们进入挂起模式,这不是系统关闭相同。

技术分享OnSessionChange(SessionChangeDescription)

在终端服务器会话中接收的更改事件时执行。

技术分享OnShutdown()

派生类中实现时,在系统关闭时执行。 指定在系统关闭之前应该发生什么。

技术分享OnStart(String[])

派生类中实现时,在由服务控制管理器 (SCM) 或在操作系统启动时 (对于自动启动的服务) 时,将启动命令发送到服务时执行。 指定当服务启动时要执行的操作。

技术分享OnStop()

派生类中实现时,停止命令发送到服务的服务控制管理器 (SCM) 时执行。 指定当服务停止运行时要执行的操作。

技术分享RequestAdditionalTime(Int32)

挂起的操作的请求更多时间。

技术分享技术分享Run(ServiceBase)

与服务控制管理器 (SCM) 注册服务的可执行文件。

技术分享技术分享Run(ServiceBase[])

注册多个服务的可执行文件与服务控制管理器 (SCM)。

技术分享ServiceMainCallback(Int32, IntPtr)

此 API 支持 产品 基础结构,不应从代码直接使用。 注册命令处理程序,然后启动该服务。

技术分享Stop()

停止正在执行的服务。

技术分享ToString()

返回 String 包含名称的 Component, ,如果有的话。 不应重写此方法。(继承自 Component。)

字段
 
 
 名称说明
技术分享技术分享MaxNameLength

指示服务名称的最大大小。

事件
 
 
 名称说明
技术分享Disposed

通过调用释放组件时发生 Dispose 方法。(继承自 Component。)

备注
 
 

派生自 ServiceBase 在服务应用程序中定义您的服务类时。 任何有用的服务的替代 OnStart 和 OnStop 方法。 对于其他功能,您可以重写 OnPause 和 OnContinue 用特定行为的服务状态变化。

服务是长时间运行的可执行文件不支持用户界面,并可能无法在已登录的用户帐户下运行。 该服务可以没有任何登录到计算机的用户的情况下运行。

默认情况下,服务不是管理员帐户相同的系统帐户下运行。 不能更改系统帐户的权限。 或者,可以使用 ServiceProcessInstaller 来指定将在其下运行服务的用户帐户。

一个可执行文件可以包含多个服务,但必须包含一个单独 ServiceInstaller 为每个服务。 ServiceInstaller 实例向系统注册该服务。 安装程序还将每个服务与事件日志用于记录服务命令相关联。 main() 函数可执行文件中的定义的服务应该运行。 该服务的当前工作目录是系统目录中,不是可执行文件所在的目录。

当您启动服务时,系统查找可执行文件,并运行 OnStart 可执行文件中包含该服务的方法。 但是,运行该服务不是运行可执行文件一样。 可执行文件仅加载服务。 访问此服务时 (例如,启动和停止) 通过服务控制管理器。

可执行文件调用 ServiceBase 派生类的第一个构造函数时调用该服务上的启动。 OnStart 构造函数执行后立即调用命令处理方法。 构造函数不会执行加载服务后,在首次后再次因此有必要单独的由中执行的构造函数执行的处理 OnStart。 可以通过释放任何资源 OnStop 应中创建 OnStart。 在构造函数中创建资源会阻止他们正在正确创建,如果服务启动后再次 OnStop 具有已释放的资源。

服务控制管理器 (SCM) 使您能够与服务交互。 SCM 可用于将开始、 停止、 暂停、 继续或自定义命令传递到服务。 SCM 使用的值 CanStop 和 CanPauseAndContinue 来确定服务是否接受停止、 暂停或继续命令。 停止、 暂停和继续在 SCM 的上下文菜单才中启用相应的属性 CanStop 或 CanPauseAndContinue 是 true 在服务类中。 如果启用,则将命令传递到服务,并 OnStop, ,OnPause, ,或 OnContinue 调用。 如果CanStop, ,CanShutdown, ,或 CanPauseAndContinue 是 false, ,相应的命令处理方法 (如 OnStop) 将不会处理,即使您已实现该方法。

您可以使用 ServiceController 类以编程方式执行 SCM 未使用的用户界面。 您可以自动化可在控制台中执行的任务。 如果 CanStop, ,CanShutdown, ,或 CanPauseAndContinue 是 true 但尚未实现相应的命令处理方法 (如 OnStop) 系统引发异常,并将忽略该命令。

不需要实现 OnStart, ,OnStop, ,或在任何其他方法 ServiceBase。 但是,该服务的行为详见 OnStart, ,因此,在最低限度下,应重写该成员。main() 函数的可执行文件中注册服务可执行文件使用服务控制管理器中,通过调用 Run 方法。 ServiceName 属性 ServiceBase 对象传递给 Run 方法必须与匹配 ServiceName 该服务的服务安装程序的属性。

您可以使用 InstallUtil.exe 若要在您的系统上安装服务。

技术分享说明

您可以指定日志而非应用程序事件日志,以接收通知的服务调用,但既不 AutoLog 和 EventLog 属性可以写入自定义日志。 设置 AutoLog 到 false 如果不想使用自动记录。

版本信息
 
 
.NET Framework 
自 1.1 起可用
线程安全
 
 

此类型的所有公共静态(Visual Basic 中的 已共享 在 Visual Basic 中)成员都是线程安全的。不保证所有实例成员都是线程安全的。

另请参阅
 
 

ServiceProcessInstaller
ServiceInstaller
System.ServiceProcess 命名空间

ServiceBase 类

 为将作为服务应用程序的一部分而存在的服务提供基类。在创建新的服务类时,必须从 ServiceBase 派生。

命名空间:System.ServiceProcess
程序集:System.ServiceProcess(在 system.serviceprocess.dll 中)

语法
 
 
C#
C++
VB
 
public class ServiceBase : Component
J#
 
public class ServiceBase extends Component
JScript
 
public class ServiceBase extends Component
备注
 
 

当在服务应用程序中定义服务类时从 ServiceBase 派生。任何有用的服务均将重写 OnStart 和 OnStop 方法。对于其他功能,可以用特定行为重写 OnPause 和 OnContinue 来响应服务状态的更改。

服务是长时间运行的可执行文件,它不支持用户界面,在登录的用户帐户下可能无法运行。服务可以在没有任何用户登录计算机的情况下运行。

默认情况下,服务在“系统”帐户下运行,该帐户与“管理员”帐户不同。不能更改“系统”帐户的权限。或者,可以使用 ServiceProcessInstaller 指定运行服务时将使用的用户帐户。

一个可执行文件可以包含多项服务,但对每项服务均必须包含一个单独的 ServiceInstaller。ServiceInstaller 实例在系统中注册服务。安装程序还将每项服务与一个事件日志关联,您可以使用该日志记录服务命令。可执行文件中的 main() 函数定义哪些服务应该运行。服务的当前工作目录是系统目录,而不是可执行文件所位于的目录。

当启动某项服务时,系统将定位相应的可执行文件,并运行该服务的 OnStart 方法(它包含在可执行文件内)。但是,运行服务与运行可执行文件并不相同。可执行文件仅加载服务。服务则通过“服务控制管理器”访问(例如启动和停止)。

当您对服务首次调用“开始”时,可执行文件调用 ServiceBase 派生类的构造函数。在构造函数执行之后将立即调用 OnStart 命令处理方法。在服务首次加载之后,构造函数不会再次执行,因此有必要将构造函数执行的处理和 OnStart 执行的处理分开。可以由 OnStop 释放的任何资源都应在 OnStart 中创建。如果服务在 OnStop 释放资源后再次启动,那么,在构造函数中创建资源会妨碍这些资源的正确创建。

“服务控制管理器”(SCM) 提供与服务交互的方式。可以使用 SCM 将“开始”(Start)、“停止”(Stop)、“暂停”(Pause)、“继续”(Continue) 或自定义命令传递到服务中。SCM 使用 CanStop 和 CanPauseAndContinue 的值,决定服务是否接受“停止”、“暂停”或“继续”命令。仅当服务类中相应的属性 CanStop 或 CanPauseAndContinue 为 true 时,才会在 SCM 的上下文菜单中启用“停止”、“暂停”或“继续”。如果已启用,则相应的命令将传递到服务,并且调用 OnStopOnPause 或 OnContinue。如果 CanStop、CanShutdown 或 CanPauseAndContinue 为 false,则即使已实现相应的命令处理方法(如 OnStop),也不会予以处理。

可以使用 ServiceController 类通过编程实现 SCM 使用用户界面实现的功能。可以自动处理控制台中可用的任务。如果 CanStopCanShutdown 或 CanPauseAndContinue 为 true,但尚未实现相应的命令处理方法(如 OnStop),则系统引发异常并忽略该命令。

不必在 ServiceBase 中实现 OnStartOnStop 或其他任何方法。然而,服务的行为在 OnStart 中加以描述,因此至少应重写该成员。必须在可执行文件的 main() 函数中设置服务的服务名称。在 main() 中设置的服务名称必须与服务安装程序的 ServiceName 属性完全匹配。

可以使用 InstallUtil.exe 在系统中安装服务。

技术分享注意

可以指定“应用程序”事件日志之外的日志来接收服务调用通知,但 AutoLog 和 EventLog 属性都不能写入自定义日志。如果不想使用自动记录,请将 AutoLog 设置为 false

示例
 
 

下面的示例从 ServiceBase 类中派生简单的服务实现。该服务处理各种服务命令,包括“停止”、“开始”、“暂停”、“继续”和自定义命令。

 

  1 // Turn on logging to the event log.  2 #define LOGEVENTS  3   4 using System;  5 using System.IO;  6 using System.Threading;  7 using System.Collections.Generic;  8 using System.ComponentModel;  9 using System.Data; 10 using System.Diagnostics; 11 using System.ServiceProcess; 12 using System.Text; 13 using Microsoft.Win32; 14 using System.Runtime.InteropServices; 15 using System.Windows.Forms; 16  17 namespace ServiceSample 18 { 19     // Define custom commands for the SimpleService. 20     public enum SimpleServiceCustomCommands { StopWorker = 128, RestartWorker, CheckWorker }; 21     [StructLayout(LayoutKind.Sequential)] 22     public struct SERVICE_STATUS 23     { 24         public int serviceType; 25         public int currentState; 26         public int controlsAccepted; 27         public int win32ExitCode; 28         public int serviceSpecificExitCode; 29         public int checkPoint; 30         public int waitHint; 31     } 32  33     public enum State 34     { 35         SERVICE_STOPPED = 0x00000001, 36         SERVICE_START_PENDING = 0x00000002, 37         SERVICE_STOP_PENDING = 0x00000003, 38         SERVICE_RUNNING = 0x00000004, 39         SERVICE_CONTINUE_PENDING = 0x00000005, 40         SERVICE_PAUSE_PENDING = 0x00000006, 41         SERVICE_PAUSED = 0x00000007, 42     } 43  44     // Define a simple service implementation. 45     public class SimpleService : System.ServiceProcess.ServiceBase 46     { 47         private static int userCount = 0; 48         private static ManualResetEvent pause = new ManualResetEvent(false); 49  50         [DllImport("ADVAPI32.DLL", EntryPoint = "SetServiceStatus")] 51         public static extern bool SetServiceStatus( 52                         IntPtr hServiceStatus, 53                         SERVICE_STATUS lpServiceStatus 54                         ); 55         private SERVICE_STATUS myServiceStatus; 56  57         private Thread workerThread = null; 58  59         public SimpleService() 60         { 61             CanPauseAndContinue = true; 62             CanHandleSessionChangeEvent = true; 63             ServiceName = "SimpleService"; 64         } 65  66         static void Main() 67         { 68 #if LOGEVENTS 69             EventLog.WriteEntry("SimpleService.Main", DateTime.Now.ToLongTimeString() + 70                 " - Service main method starting..."); 71 #endif 72  73             // Load the service into memory. 74             System.ServiceProcess.ServiceBase.Run(new SimpleService()); 75  76 #if LOGEVENTS 77             EventLog.WriteEntry("SimpleService.Main", DateTime.Now.ToLongTimeString() + 78                 " - Service main method exiting..."); 79 #endif 80  81         } 82  83         private void InitializeComponent() 84         { 85             // Initialize the operating properties for the service. 86             this.CanPauseAndContinue = true; 87             this.CanShutdown = true; 88             this.CanHandleSessionChangeEvent = true; 89             this.ServiceName = "SimpleService"; 90         } 91  92         // Start the service. 93         protected override void OnStart(string[] args) 94         { 95             IntPtr handle = this.ServiceHandle; 96             myServiceStatus.currentState = (int)State.SERVICE_START_PENDING; 97             SetServiceStatus(handle, myServiceStatus); 98  99             // Start a separate thread that does the actual work.100 101             if ((workerThread == null) ||102                 ((workerThread.ThreadState &103                  (System.Threading.ThreadState.Unstarted | System.Threading.ThreadState.Stopped)) != 0))104             {105 #if LOGEVENTS106                 EventLog.WriteEntry("SimpleService.OnStart", DateTime.Now.ToLongTimeString() +107                     " - Starting the service worker thread.");108 #endif109 110                 workerThread = new Thread(new ThreadStart(ServiceWorkerMethod));111                 workerThread.Start();112             }113             if (workerThread != null)114             {115 #if LOGEVENTS116                 EventLog.WriteEntry("SimpleService.OnStart", DateTime.Now.ToLongTimeString() +117                     " - Worker thread state = " +118                     workerThread.ThreadState.ToString());119 #endif120             }121             myServiceStatus.currentState = (int)State.SERVICE_RUNNING;122             SetServiceStatus(handle, myServiceStatus);123 124         }125 126         // Stop this service.127         protected override void OnStop()128         {129             // New in .NET Framework version 2.0.130             this.RequestAdditionalTime(4000);131             // Signal the worker thread to exit.132             if ((workerThread != null) && (workerThread.IsAlive))133             {134 #if LOGEVENTS135                 EventLog.WriteEntry("SimpleService.OnStop", DateTime.Now.ToLongTimeString() +136                     " - Stopping the service worker thread.");137 #endif138                 pause.Reset();139                 Thread.Sleep(5000);140                 workerThread.Abort();141 142             }143             if (workerThread != null)144             {145 #if LOGEVENTS146                 EventLog.WriteEntry("SimpleService.OnStop", DateTime.Now.ToLongTimeString() +147                     " - OnStop Worker thread state = " +148                     workerThread.ThreadState.ToString());149 #endif150             }151             // Indicate a successful exit.152             this.ExitCode = 0;153         }154 155         // Pause the service.156         protected override void OnPause()157         {158             // Pause the worker thread.159             if ((workerThread != null) &&160                 (workerThread.IsAlive) &&161                 ((workerThread.ThreadState &162                  (System.Threading.ThreadState.Suspended | System.Threading.ThreadState.SuspendRequested)) == 0))163             {164 #if LOGEVENTS165                 EventLog.WriteEntry("SimpleService.OnPause", DateTime.Now.ToLongTimeString() +166                     " - Pausing the service worker thread.");167 #endif168 169                 pause.Reset();170                 Thread.Sleep(5000);171             }172 173             if (workerThread != null)174             {175 #if LOGEVENTS176                 EventLog.WriteEntry("SimpleService.OnPause", DateTime.Now.ToLongTimeString() +177                     " OnPause - Worker thread state = " +178                     workerThread.ThreadState.ToString());179 #endif180             }181         }182 183         // Continue a paused service.184         protected override void OnContinue()185         {186 187             // Signal the worker thread to continue.188             if ((workerThread != null) &&189                 ((workerThread.ThreadState &190                  (System.Threading.ThreadState.Suspended | System.Threading.ThreadState.SuspendRequested)) != 0))191             {192 #if LOGEVENTS193                 EventLog.WriteEntry("SimpleService.OnContinue", DateTime.Now.ToLongTimeString() +194                     " - Resuming the service worker thread.");195 196 #endif197                 pause.Set();198             }199             if (workerThread != null)200             {201 #if LOGEVENTS202                 EventLog.WriteEntry("SimpleService.OnContinue", DateTime.Now.ToLongTimeString() +203                     " OnContinue - Worker thread state = " +204                     workerThread.ThreadState.ToString());205 #endif206             }207         }208 209         // Handle a custom command.210         protected override void OnCustomCommand(int command)211         {212 #if LOGEVENTS213             EventLog.WriteEntry("SimpleService.OnCustomCommand", DateTime.Now.ToLongTimeString() +214                 " - Custom command received: " +215                 command.ToString());216 #endif217 218             // If the custom command is recognized,219             // signal the worker thread appropriately.220 221             switch (command)222             {223                 case (int)SimpleServiceCustomCommands.StopWorker:224                     // Signal the worker thread to terminate.225                     // For this custom command, the main service226                     // continues to run without a worker thread.227                     OnStop();228                     break;229 230                 case (int)SimpleServiceCustomCommands.RestartWorker:231 232                     // Restart the worker thread if necessary.233                     OnStart(null);234                     break;235 236                 case (int)SimpleServiceCustomCommands.CheckWorker:237 #if LOGEVENTS238                     // Log the current worker thread state.239                     EventLog.WriteEntry("SimpleService.OnCustomCommand", DateTime.Now.ToLongTimeString() +240                         " OnCustomCommand - Worker thread state = " +241                         workerThread.ThreadState.ToString());242 #endif243 244                     break;245 246                 default:247 #if LOGEVENTS248                     EventLog.WriteEntry("SimpleService.OnCustomCommand",249                         DateTime.Now.ToLongTimeString());250 #endif251                     break;252             }253         }254         // Handle a session change notice255         protected override void OnSessionChange(SessionChangeDescription changeDescription)256         {257 #if LOGEVENTS258             EventLog.WriteEntry("SimpleService.OnSessionChange", DateTime.Now.ToLongTimeString() +259                 " - Session change notice received: " +260                 changeDescription.Reason.ToString() + "  Session ID: " + 261                 changeDescription.SessionId.ToString());262 #endif263 264             switch (changeDescription.Reason)265             {266                 case SessionChangeReason.SessionLogon:267                     userCount += 1;268 #if LOGEVENTS269                     EventLog.WriteEntry("SimpleService.OnSessionChange", 270                         DateTime.Now.ToLongTimeString() +271                         " SessionLogon, total users: " +272                         userCount.ToString());273 #endif274                     break;275 276                 case SessionChangeReason.SessionLogoff:277 278                     userCount -= 1;279 #if LOGEVENTS280                     EventLog.WriteEntry("SimpleService.OnSessionChange", 281                         DateTime.Now.ToLongTimeString() +282                         " SessionLogoff, total users: " +283                         userCount.ToString());284 #endif285                     break;286                 case SessionChangeReason.RemoteConnect:287                     userCount += 1;288 #if LOGEVENTS289                     EventLog.WriteEntry("SimpleService.OnSessionChange", 290                         DateTime.Now.ToLongTimeString() +291                         " RemoteConnect, total users: " +292                         userCount.ToString());293 #endif294                     break;295 296                 case SessionChangeReason.RemoteDisconnect:297 298                     userCount -= 1;299 #if LOGEVENTS300                     EventLog.WriteEntry("SimpleService.OnSessionChange", 301                         DateTime.Now.ToLongTimeString() +302                         " RemoteDisconnect, total users: " +303                         userCount.ToString());304 #endif305                     break;306                 case SessionChangeReason.SessionLock:307 #if LOGEVENTS308                     EventLog.WriteEntry("SimpleService.OnSessionChange", 309                         DateTime.Now.ToLongTimeString() + 310                         " SessionLock");311 #endif312                     break;313 314                 case SessionChangeReason.SessionUnlock:315 #if LOGEVENTS316                     EventLog.WriteEntry("SimpleService.OnSessionChange", 317                         DateTime.Now.ToLongTimeString() + 318                         " SessionUnlock");319 #endif320                     break;321 322                 default:323 324                     break;325             }326         }327         // Define a simple method that runs as the worker thread for 328         // the service.  329         public void ServiceWorkerMethod()330         {331 #if LOGEVENTS332             EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() +333                 " - Starting the service worker thread.");334 #endif335 336             try337             {338                 do339                 {340                     // Simulate 4 seconds of work.341                     Thread.Sleep(4000);342                     // Block if the service is paused or is shutting down.343                     pause.WaitOne();344 #if LOGEVENTS345                     EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() +346                         " - heartbeat cycle.");347 #endif348                 }349                 while (true);350             }351             catch (ThreadAbortException)352             {353                 // Another thread has signalled that this worker354                 // thread must terminate.  Typically, this occurs when355                 // the main service thread receives a service stop 356                 // command.357 358                 // Write a trace line indicating that the worker thread359                 // is exiting.  Notice that this simple thread does360                 // not have any local objects or data to clean up.361 #if LOGEVENTS362                 EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() +363                     " - Thread abort signaled.");364 #endif365             }366 #if LOGEVENTS367 368             EventLog.WriteEntry("SimpleService.WorkerThread", DateTime.Now.ToLongTimeString() +369                 " - Exiting the service worker thread.");370 #endif371 372         }373     }374 }

 

ServiceBase 类