2011-02-01 112 views
46

我创建了一个名为ProxyMonitor的Windows服务,而我目前正在按照我想要的方式安装和卸载服务。Windows服务不断运行

所以我执行的应用程序,像这样:

C:\\Windows\\Vendor\\ProxyMonitor.exe /install 

漂亮的自我解释,然后我到services.msc和并启动该服务,但我这样做时,我得到了以下信息:

本地计算机上的代理监视器服务已启动,然后停止。如果没有工作要做,比如一些服务自动停止,性能日志和警报服务

我的代码看起来像这样:

public static Main(string[] Args) 
{ 
    if (System.Environment.UserInteractive) 
    { 
     /* 
      * Here I have my install logic 
     */ 
    } 
    else 
    { 
     ServiceBase.Run(new ProxyMonitor()); 
    } 
} 

然后ProxyMonitor类中我有:

public ProxyMonitor() 
{ 
} 

protected override void OnStart(string[] args) 
{ 
    base.OnStart(args); 
    ProxyEventLog.WriteEntry("ProxyMonitor Started"); 

    running = true; 
    while (running) 
    { 
     //Execution Loop 
    } 
} 

onStop()我只是将running变量更改为false;

我需要怎么做才能使服务不断活跃,因为我将需要监控网络我需要跟踪变化等


更新:1

protected override void OnStart(string[] args) 
{ 
    base.OnStart(args); 
    ProxyEventLog.WriteEntry("ProxyMonitor Started"); 

    Thread = new Thread(ThreadWorker); 
    Thread.Start(); 
} 

ThreadWorker我有ProxyEventLogger.WriteEntry("Main thread entered")哪些不会被解雇。

+0

`线程=新主题(ThreadWorker)`不会工作 – 2011-02-01 16:10:05

+0

工作完全正常,为什么你认为它会失败? – RobertPitt 2011-02-01 22:37:45

回答

117

OnStart()回调需要及时返回,因此您需要开始执行所有工作的线程。我会建议增加以下字段类:

using System.Threading; 
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false); 
private Thread _thread; 

_thread场将保留对您的OnStart()回调创建System.Threading.Thread对象的引用。 _shutdownEvent字段包含系统级别的事件结构,该结构将用于指示线程在服务关闭时停止运行。

OnStart()回调中,创建并启动您的线程。

protected override void OnStart(string[] args) 
{ 
    _thread = new Thread(WorkerThreadFunc); 
    _thread.Name = "My Worker Thread"; 
    _thread.IsBackground = true; 
    _thread.Start(); 
} 

您需要一个名为WorkerThreadFunc的函数才能使其工作。它必须匹配System.Threading.ThreadStart代表签名。

private void WorkerThreadFunc() 
{ 
} 

如果你不把任何东西在这个函数中,该线程将启动,然后立即关闭,所以你必须把一些逻辑在里面,基本上保持线程活着,而你做你的工作。这就是_shutdownEvent派上用场的地方。

private void WorkerThreadFunc() 
{ 
    while (!_shutdownEvent.WaitOne(0)) { 
     // Replace the Sleep() call with the work you need to do 
     Thread.Sleep(1000); 
    } 
} 

while循环检查ManualResetEvent以查看它是否“设置”。由于我们在上面初始化了对象false,所以此检查返回false。在圈内,我们睡了1秒。您需要将其替换为您需要执行的工作 - 监视代理设置等。

最后,在您的Windows服务的OnStop()回调中,想要发信号通知线程停止运行。这很容易使用_shutdownEvent

protected override void OnStop() 
{ 
    _shutdownEvent.Set(); 
    if (!_thread.Join(3000)) { // give the thread 3 seconds to stop 
     _thread.Abort(); 
    } 
} 

希望这会有所帮助。

0

为什么不在您的Windows Service类型的解决方案中创建一个新项目?这设置了您需要实现的所有结构,包括用于服务启动/停止事件的处理程序。

+1

这部分是一种培训体验,我更愿意从底层学习它的做法。 – RobertPitt 2011-02-01 15:52:54

+0

我认为,即使是培训(尤其是培训?),您最好学习如何为Windows服务创建脚手架,然后了解它为什么可以工作以及它如何工作。而不是自下而上,正如你所发现的那样,更令人沮丧。 – 2011-02-01 16:03:13

6

您需要退出您的OnStart处理程序,以便服务控制器意识到您的服务实际已启动。为了使它像你想要的那样工作,你可以启动一个计时器,该计时器在一个时间间隔内进行打勾并在打勾时进行处理。

编辑:

尝试把一个System.Diagnostics.Debugger.Launch()在你的OnStart,看看发生了什么(将断点设置在ThreadWorker)。我建议在#if DEBUG中包装这个以确保它不会被部署。

我也意识到,你不给你Thread一个名字:

Thread myThread = new Thread(ThreadWorker); 
myThread.Start(); 
2

当然不是在OnStart方法添加while循环。这将对操作系统说服务尚未启动,因为它无法从OnStart方法安全地退出。我通常会创建一个在OnStart方法中启用的Timer。然后在Ticks方法中,我确实调用了必要的方法以便让应用程序运行。

或者,你可以做到以下几点:

// The main entry point for the process 
static void Main() 
{ 
    System.ServiceProcess.ServiceBase[] ServicesToRun; 
    ServicesToRun = new System.ServiceProcess.ServiceBase[] { new WinService1() }; 
    System.ServiceProcess.ServiceBase.Run(ServicesToRun); 
} 

有关Windows服务的更多信息,你可以得到一个骨架例子here

1

使用控制台应用演示的示例代码。希望这将有助于..

class Program 
{ 
    private static CancellationTokenSource _cancellationTokenSource; 
    private static ManualResetEvent _shutdownEvent = new ManualResetEvent(false); 
    private static Thread _serviceStartThread; 
    private static Thread _serviceStopThread; 

    private static int workcounter = 0; 
    static void Main(string[] args) 
    { 

     _cancellationTokenSource = new CancellationTokenSource(); 
     _serviceStartThread = new Thread(DoWork); 
     _serviceStopThread = new Thread(ScheduledStop); 
     StartService(); 
     StopService(); 
    } 

    private static void StartService() 
    { 
     _serviceStartThread.Start(); 

    } 

    private static void StopService() 
    { 
     _serviceStopThread.Start(); 
    } 


    /// <summary> 
    /// Triggers a cancellation event for stopping the service in a timely fashion. 
    /// </summary> 
    private static void ScheduledStop() 
    { 
     while (!_shutdownEvent.WaitOne(0)) 
     { 
      if (workcounter == 10) 
      { 
       _cancellationTokenSource.Cancel(); 
      } 
     } 
    } 

    /// <summary> 
    /// Represents a long running Task with cancellation option 
    /// </summary> 
    private static void DoWork() 
    { 

     while (!_shutdownEvent.WaitOne(0)) 
     { 
      if(!_cancellationTokenSource.Token.IsCancellationRequested) 
      { 
       workcounter += 1; 
       Console.Write(Environment.NewLine); 
       Console.Write("Running...counter: " + workcounter.ToString()); 
       Thread.Sleep(1000);//Not needed, just for demo.. 
      } 
      else 
      { 
       Console.Write(Environment.NewLine); 
       Console.Write("Recieved cancellation token,shutting down in 5 seconds.. counter: " + workcounter.ToString()); 
       _shutdownEvent.Set(); 
       Thread.Sleep(5000);//Not needed, just for demo.. 
      } 

     } 
    } 
}