重复执行一个代码块而不超时.windows服务
本文关键字:超时 服务 windows 代码 一个 执行 复执 | 更新日期: 2023-09-27 18:11:37
我写了一个简单的windows服务,下面是它的框架:
internal class ServiceModel {
private Thread workerThread;
private AutoResetEvent finishedEvent;
private Int32 timeout = 60000*15;
public void Start() {
this.workerThread = new Thread(this.Process);
this.finishedEvent = new AutoResetEvent(false);
this.workerThread.Start();
}
public void Stop() {
this.finishedEvent.Set();
this.workerThread.Join(30000);
}
public void Process() {
while(!this.finishedEvent.WaitOne(timeout)) {
// run things here
}
}
}
我不能理解的第一件事是服务在运行前等待一个超时。将new AutoResetEvent(false);
重写为new AutoResetEvent(true);
会导致服务不等待就启动吗?
第二件事
由于一些内部原因(从外部服务器/服务请求数据,异常处理),有时等待修复15是不够的。30分钟超时。
我如何重写它的工作没有固定超时?我是否需要删除AutoResetEvent
实例,并在无限循环中运行Process
主体?
public void Process() {
while(true) {
// run things here
}
}
编辑。try - catch/锁
在Process
方法中有一个全局try-catch
块:
public void Process() {
do {
try {
// processing goes here
}
catch(Exception ex) {
Logger.Log.Warn(ex); // or Log.Fatal(ex)...
}
}
while(true);
}
如果我使用同步对象我在哪里放置lock
语句,以便我能够在isStopped
为真时调用break
?
您不必处理低级线程和同步原语API。考虑使用任务并行库(TPL)。使用TPL取消框架很容易实现OnStop
:
using System.ServiceProcess;
using System.Threading;
using System.Threading.Tasks;
namespace WindowsService1
{
public partial class Service1 : ServiceBase
{
CancellationTokenSource _mainCts;
Task _mainTask;
public Service1()
{
InitializeComponent();
}
async Task MainTaskAsync(CancellationToken token)
{
while (true)
{
token.ThrowIfCancellationRequested();
// ...
await DoPollingAsync(token);
// ...
}
}
protected override void OnStart(string[] args)
{
_mainCts = new CancellationTokenSource();
_mainTask = MainTaskAsync(_mainCts.Token);
}
protected override void OnStop()
{
_mainCts.Cancel();
try
{
_mainTask.Wait();
}
catch
{
if (!_mainTask.IsCanceled)
throw;
}
}
}
}
在MainTaskAsync
中,您可以将Task.Run
用于任何cpu绑定的工作项。
使用线程,您可以使用以下代码实现您的需求:
internal class ServiceModel {
private Thread workerThread;
private object syncLock = new object();
private bool stop = false;
public void Start() {
this.workerThread = new Thread(this.Process);
this.workerThread.Start();
}
public void Stop() {
lock(syncLock) stop = true;
this.workerThread.Join(30000);
}
public void Process() {
while(true){
//your stuff here.
lock(syncLock)
{
if(stop)
break;
}
Thread.Sleep(30000);
}
}
}