在没有超时的情况下重复执行代码块。 Windows服务

时间:2014-07-07 06:44:51

标签: c# .net multithreading

我写了一个简单的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>

2 个答案:

答案 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); 
        }
    }
}