使用 WaitHandle.WaitOne

Using WaitHandle.WaitOne

我正在尝试创建一个 windows 服务,该服务每 5 分钟轮询一次系统并检查是否需要执行某些操作。我已经阅读了 WaitHandles 及其在该领域的用处,但需要了解其工作原理。

查看下面的代码:

public partial class PollingService : ServiceBase
{
    private CancellationTokenSource cancelToken = new CancellationTokenSource();
    private Task mainTask = null;
    public PollingService()
    {
        InitializeComponent();  
    }
    protected override void OnStart(string[] args)
    {   
        mainTask = new Task(pollInterval, cancelToken.Token, TaskCreationOptions.LongRunning);
        mainTask.Start();
    }
    public void pollInterval()
    {
        CancellationToken cancel = cancelToken.Token;
        TimeSpan interval = TimeSpan.FromMinutes(5);
        while (!cancel.IsCancellationRequested && !cancel.WaitHandle.WaitOne(interval))
        {
            if (cancel.IsCancellationRequested)
            {
                break;
            }
            EventLog.WriteEntry("*-HEY MAN I'M POLLNG HERE!!-*");
            //Polling code goes here. Checks periodically IsCancellationRequested
        }
    }
    protected override void OnStop()
    {
        cancelToken.Cancel();
        mainTask.Wait();
    }
}

根据我的研究,上面的代码似乎应该有效,但我不理解 !cancel.WaitHandle.WaitOne(interval) 部分。这如何让循环每五分钟等待一次呢?我需要理解这部分代码才能完成我的脚本,或者知道我在使用 WaitHandle 时是否完全错误。

这是我的灵感来源:Creating a c# windows service to poll a database

正如 Hans 指出的文章所解释的那样,这里的用法是让线程等待某个特定的时间段,但仍然允许线程在超时期限到期之前被唤醒,例如如果您需要线程提前终止(如此处)。

也就是说,这个实现是 "old school"。 :) 如果您使用的是 .NET 4.5,恕我直言,如果您使用 async/await 习惯用法(特别是因为您已经在使用 CancellationTokenSource),代码会更好地工作:

    protected async override void OnStart(string[] args)
    {   
        try
        {
            await pollInterval();
        }
        catch (TaskCanceledException) { }
    }

    public async Task pollInterval()
    {
        CancellationToken cancel = cancelToken.Token;
        TimeSpan interval = TimeSpan.FromMinutes(5);
        while (true)
        {
            await Task.Delay(interval, cancel);
            EventLog.WriteEntry("*-HEY MAN I\"M POLLNG HERE!!-*");
            //Polling code goes here. Checks periodically IsCancellationRequested
        }
    }

通过以上,代码更准确地表达了意图。也就是说,尽管 WaitHandle 版本主要是在等待信号退出,尽管工作的主要机制实际上是等待超时,但这里的代码清楚地表明主要意图是延迟,有可能取消延迟。