簡體   English   中英

Windows 服務不斷運行

[英]Windows Service to run constantly

我已經創建了一個名為ProxyMonitor的 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")它不會被觸發。

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();
     }
} 

希望這會有所幫助。

您需要退出OnStart處理程序,以便服務控制器意識到您的服務已實際啟動。 為了讓它像你想要的那樣工作,你可以啟動一個定時器,它在一個時間間隔內滴答作響,並在它滴答作響時進行處理。

編輯:

嘗試在OnStart放置 System.Diagnostics.Debugger.Launch() 以查看發生了什么(並在ThreadWorker放置一個斷點)。 我建議將其包裝在#if DEBUG以確保它不會被部署。

我剛剛也意識到你沒有給你的Thread一個名字:

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

使用控制台應用程序演示的示例代碼。 希望這會有所幫助..

 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..
            }

        }
    }
}

當然不會在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 服務的更多信息,您可以在此處獲取框架示例。

為什么不在 Windows 服務類型的解決方案中創建一個新項目? 這設置了您需要實現的所有結構,甚至包括服務啟動/停止事件的處理程序。

在我看來,解決這個問題最簡單的方法是:

protected override void OnStart(string[] args)
{            
    new Task(() =>
    {
            new ProxyMonitor();                    
    }).Start();    
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM