C# Windows服务在正常关机的情况下对计时器执行工作
我正在尝试创建一个Windows服务,它可以在计时器上执行作业,并且可以正常关闭。我在这里使用了各种各样的问题/答案来产生下面的代码。它可以工作,但我想确保它是最正确和优雅的解决方案。我也有一些具体的问题(在代码之后) 这是主要的服务类C# Windows服务在正常关机的情况下对计时器执行工作,c#,C#,我正在尝试创建一个Windows服务,它可以在计时器上执行作业,并且可以正常关闭。我在这里使用了各种各样的问题/答案来产生下面的代码。它可以工作,但我想确保它是最正确和优雅的解决方案。我也有一些具体的问题(在代码之后) 这是主要的服务类 using System; using System.ServiceProcess; using System.Threading; using System.Threading.Tasks; using System.Timers; namespace My
using System;
using System.ServiceProcess;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;
namespace MyService
{
public class MyService : ServiceBase
{
CancellationTokenSource cancellationTokenSource;
System.Timers.Timer serviceTimer;
Task workTask;
public static void Main(string[] args)
{
if (!Environment.UserInteractive)
{
Run(new MyService());
}
}
protected override void OnStart(string[] args)
{
cancellationTokenSource = new CancellationTokenSource();
serviceTimer = new System.Timers.Timer(30000);
serviceTimer.Elapsed += new ElapsedEventHandler(serviceTimer_Elapsed);
serviceTimer.Start();
}
protected override void OnStop()
{
try
{
serviceTimer.Stop();
cancellationTokenSource.Cancel();
if (workTask != null)
{
workTask.Wait(10000);
}
}
finally
{
serviceTimer.Dispose();
serviceTimer = null;
cancellationTokenSource.Dispose();
cancellationTokenSource = null;
}
}
private void serviceTimer_Elapsed(object sender, ElapsedEventArgs e)
{
serviceTimer.Stop();
workTask = Task.Run(() => StartWorkMethod()).ContinueWith(WorkCompleted);
}
private void WorkCompleted(Task completedTask)
{
workTask = null;
serviceTimer.Start();
}
private void StartWorkMethod()
{
Work work = new Work(cancellationTokenSource.Token);
work.StartWork();
}
}
}
这是执行(当前模拟)工作的类
使用系统线程;
命名空间MyService
{
公开课
{
取消令牌取消令牌;
公共工作(取消令牌取消令牌)
{
this.cancellationToken=cancellationToken;
}
公共网络
{
对于(int i=0;i<4;i++)
{
if(cancellationToken.IsCancellationRequested)
{
打破
}
睡眠(10000);
}
}
}
}
该服务在不阻塞处理程序线程的情况下工作并运行所有任务。如果服务停止,OnStop方法将等待任务的当前工作块完成一段时间,然后再停止(感谢Oz的Ian!)
以下是我的具体问题:
working
变量和while循环等待Work
类完成,并将bool设置为false
。这是最好的处理方法吗?已经由奥兹的伊恩回答了OnStop
方法在退出之前只会等待一定的时间。实现这一点的最佳方式是什么?已经由奥兹的伊恩回答了- 服务安装代码不包括在内,我正在使用安装程序安装服务
- 计时器控制两次执行之间的时间,以便在前一次执行耗时较长时不会出现重复执行;这就是为什么计时器在开始工作之前停止,在开始工作之后重新启动
- 我已经看到,
方法有时放在它自己的文件中,但大多数情况下可执行文件也是安装程序;在这种情况下,它只会通过Main
方法本身简化此文件Main
编辑以合并Ian of Oz的建议。您是否可以保留在serviceTimer_中创建的任务,然后添加对任务的调用。在调用取消后等待(毫秒)TokenSource.Cancel()?@IanofOz,谢谢!我测试了一下,它成功了。我想,除了我的布尔值之外,我还需要添加一个计时器来跟踪是否有工作发生。但是Task.Wait替换了布尔值,并处理了等待x时间部分。好主意!很高兴任务的想法奏效了,太棒了。你可以考虑的另一种方法是,如果你需要的话,推迟服务的停止。默认情况下,您有20秒(或者至少过去是这样,在我的Windows 8机器上检查,现在的默认时间是5秒)。这是由HKLM\SYSTEM\CurrentControlSet\Control\WaitToKillServiceTimeout处的注册表项控制的。抱歉,此处被切断。。。如果您需要更多的时间(例如完成任务),可以在ServiceBase上调用RequestAditionalTime来延迟服务的完成。您还可以将WaitToKillServiceTimeout值用于任务的较少硬编码值。等待超时值。
using System.Threading;
namespace MyService
{
public class Work
{
CancellationToken cancellationToken;
public Work(CancellationToken cancellationToken)
{
this.cancellationToken = cancellationToken;
}
public void StartWork()
{
for (int i = 0; i < 4; i++)
{
if (cancellationToken.IsCancellationRequested)
{
break;
}
Thread.Sleep(10000);
}
}
}
}