提问人:RobertPitt 提问时间:2/1/2011 最后编辑:Mark AmeryRobertPitt 更新时间:12/24/2022 访问量:82439
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")
答:
为什么不在解决方案中创建一个 Windows 服务类型的新项目?这将设置您需要实现的所有结构,甚至包括服务启动/停止事件的处理程序。
评论
您需要退出处理程序,以便服务控制器意识到您的服务实际上已启动。为了让它像你想要的那样工作,你可以启动一个计时器,它以一定的时间间隔滴答作响,并在滴答作响时进行处理。OnStart
编辑:
尝试将 System.Diagnostics.Debugger.Launch() 放入 u 中,以查看发生了什么(并在 中放置一个断点)。我建议将其包装起来以确保它不会被部署。OnStart
ThreadWorker
#if DEBUG
我刚刚也意识到你没有给你一个名字:Thread
Thread myThread = new Thread(ThreadWorker);
myThread.Start();
评论
return 0
return false
OnStart
当然不会在方法中添加循环。这将告诉操作系统,服务尚未启动,因为它无法安全地退出该方法。我通常会创建一个在方法中启用的。然后在方法中,我确实调用了必要的方法,以便让 appplicatin 运行。while
OnStart
OnStart
Timer
OnStart
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 服务的详细信息,可以在此处获取框架示例。
回调需要及时返回,因此您需要启动一个线程,在该线程中将执行所有工作。我建议将以下字段添加到您的班级中:OnStart()
using System.Threading;
private ManualResetEvent _shutdownEvent = new ManualResetEvent(false);
private Thread _thread;
该字段将保存对您在回调中创建的对象的引用。该字段包含一个系统级事件构造,该构造将用于向线程发出信号,使其在服务关闭时停止运行。_thread
System.Threading.Thread
OnStart()
_shutdownEvent
在回调中,创建并启动线程。OnStart()
protected override void OnStart(string[] args)
{
_thread = new Thread(WorkerThreadFunc);
_thread.Name = "My Worker Thread";
_thread.IsBackground = true;
_thread.Start();
}
您需要一个名为的函数才能正常工作。它必须与 System.Threading.ThreadStart
委托签名匹配。WorkerThreadFunc
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 循环检查它是否被“设置”了。由于我们用上面的东西初始化了对象,所以这个检查返回 false。在循环中,我们睡了 1 秒钟。您需要将其替换为您需要执行的工作 - 监视代理设置等。ManualResetEvent
false
最后,在 Windows 服务的回调中,您希望向线程发出停止运行的信号。这很容易使用 .OnStop()
_shutdownEvent
protected override void OnStop()
{
_shutdownEvent.Set();
if (!_thread.Join(3000)) { // give the thread 3 seconds to stop
_thread.Abort();
}
}
评论
_shutdownEvent.Set()
WorkerThreadFunc()
ManualResetEvent
使用控制台应用程序演示的示例代码。 希望这会有所帮助。.
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..
}
}
}
}
在我看来,解决这个问题的最简单方法是:
protected override void OnStart(string[] args)
{
new Task(() =>
{
new ProxyMonitor();
}).Start();
}
评论