我写了一个简单的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
语句,以便在break
为真时我可以调用isStopped
?< / p>
答案 0 :(得分:2)
您不必处理低级线程和同步原语API。考虑使用Task Parallel Library (TPL)。使用TPL cancellation framework:
可以轻松实现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限制的工作项。
答案 1 :(得分:1)
使用线程,您可以使用以下代码实现您的要求:
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);
}
}
}