[英]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.