Как эффективно управлять асинхронными задачами в сервисе Windows - PullRequest
0 голосов
/ 27 января 2020

Я пытаюсь использовать TPL в сервисе windows для эффективной асинхронной обработки. Служба работает бесконечно l oop, пока служба не будет отменена.

Вот код, который я использую для основных методов службы:

private CancellationTokenSource cancellationTokenSource;
private readonly List<Task> tasks = new List<Task>();

protected override void OnStart(string[] args)
{
    cancellationTokenSource = new CancellationTokenSource();

    tasks.Add(Task.Factory.StartNew(() =>
    {
        Worker(cancellationTokenSource.Token);
    }, cancellationTokenSource.Token));
}

private async void Worker(CancellationToken token)
{
    bool keepGoing = true;

    while (keepGoing)
    {
        try
        {
            if (token.IsCancellationRequested)
            {
                token.ThrowIfCancellationRequested();
            }
            //Parallel.ForEach(processors, processor =>
            //{
            await processor.Process();
            //});
        }
        catch (Exception ex)
        {
            if (ex is OperationCanceledException)
            {
                keepGoing = false;
            }
            else
            {
                //write log here
            }
        }
        finally
        {
            await Task.Delay(configurationSettings.OperationSettings.ServiceOperationDelay, token).ContinueWith(tsk => { });
        }
    }
}

protected override void OnStop()
{
    cancellationTokenSource.Cancel();

    using var mres = new ManualResetEventSlim();
    using (cancellationTokenSource.Token.Register(() => mres.Set()))
    {
        Task.Factory.ContinueWhenAll(tasks.ToArray(), (t) => mres.Set());
        mres.Wait();
    }
}

Вызов процессор в основном делает следующее:

var records = await interfaceService.Get()

foreach record retrieved
       await interfaceService.Patch()

Служба использует экземпляр HttpClient для выполнения запросов.

        **Get:**
        using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get,
                                         "");

        using HttpResponseMessage response = await httpClient.SendAsync(request);

        if (response.IsSuccessStatusCode)
        {
            //return results
        }
        else
        {
            throw Exception("Foo bar")
        }

        **Patch**
        using HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Patch, "")
        {
            Content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json")
        };
        using HttpResponseMessage response = await httpClient.SendAsync(request);

Проблема, с которой я сталкиваюсь, заключается в том, что если конечная точка становится недоступной, Служба просто не может эффективно отследить ни одно исключение или возвращенные ответы, и из-за отсутствия лучшей терминологии проваливается. Я полагаю, что моя проблема заключается в способе управления задачами.

В конечном итоге я хочу иметь службу с каждой итерацией l oop

  1. Выключить заданные c задачи асинхронно, которые выполняют операцию get / patch, сразу
  2. Подождите, пока все не будут завершены.
  3. Записать результаты каждой в файл
  4. Go для сна
  5. Запуск с шага # 1

Кроме того, когда служба останавливается, я хочу изящно остановить обработку каждой задачи.

Любая помощь в этом с благодарностью!

...