我正在创建一个windows服务,以便在一定的时间间隔内运行一些任务。在这里,用户可以设置任务开始时间(首次运行)和任务间隔。在我的程序中的OnStart
事件中,设置计时器并等待触发器。
但问题是主线程在线程计时器启动之前就死了。所以我尝试添加Thread.CurrentThread.Join()
和Sleep()
,直到计时器启动。但在安装windows服务后,我无法启动windows服务,因为sleep
或block
处于OnStart
事件中。所以它卡住了,或者睡了这么长时间,并显示出一些异常。
我只需要停止退出主线程,直到线程计时器触发。
public partial class Service1 : ServiceBase
{
TimerCallback timer_delegate;
Timer houskeep_timer;
protected override void OnStart(string[] args)
{
SettingReader settings = new SettingReader();
if (settings.init())
{
timer_delegate = new TimerCallback(houseKeep);
houskeep_timer = new Timer(timer_delegate, "testing", 33333100000, 44450000);
//Thread.CurrentThread.Join();
}
}
private void houseKeep(object setting_obj)
{
string message = (string)setting_obj;
writeToLogFile(message);
}
}
我不会使用计时器,我会使用一个普通的exe并在任务调度程序中设置它。否则,您只是在实现自己的调度,与windows中已经内置的功能相比,功能要少得多。
请参阅Jon Galloway关于为什么不使用服务运行计划任务的帖子。
请注意,这不是执行多线程操作的最佳方式,但它可能是解决问题的方法
使用对踏板全局的布尔变量。把它放在主踏板上,看看它是否改变了!当您希望主线程退出时,请在服务步骤中更改它。之后,主线程将在您想要的时间退出。只要在踏板之间创建的标志是bool
,就不需要执行任何invoke
方法或其他操作。
这将实现您需要的
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace WindowsService1
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
private System.Threading.AutoResetEvent are = new System.Threading.AutoResetEvent(false);
protected override void OnStart(string[] args)
{
new System.Threading.Thread(mt) { IsBackground = true }.Start();
}
private void mt()
{
// Set up timer here
// wait for OnStop indefinitely
are.WaitOne();
}
protected override void OnStop()
{
are.Set();
}
}
}
OnStart将启动一个无限期等待OnStop的线程。正是在这个线程中,您将创建计时器。