Использование 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.

Именно здесь у меня возникла идея: Создание службы Windows c # для опросить базу данных


person steventnorris    schedule 04.02.2015    source источник


Ответы (1)


Как поясняет статья, на которую указывает Ханс, здесь используется способ заставить поток ждать в течение определенного периода времени, но при этом позволять потоку просыпаться до истечения периода тайм-аута, например в случае, если вам нужно преждевременно завершить поток (как здесь).

Тем не менее, это реализация «старой школы». :) Если вы используете .NET 4.5, IMHO код будет работать лучше, если вы используете идиому _1 _ / _ 2_ (тем более, что вы уже используете 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, по-видимому, в первую очередь ожидает сигнала о выходе, даже несмотря на то, что основным действующим механизмом на самом деле является тайм-аут для ожидания, здесь код ясно указывает, что основное намерение состоит в задержке с возможностью задержка отменяется.

person Peter Duniho    schedule 05.02.2015