Проблема с CancellationTokenSource в C# - PullRequest
0 голосов
/ 28 апреля 2020

Я пытаюсь создать вспомогательный класс для периодической отправки некоторой информации на внутренний сервер. Прикрепленный ниже код.

public class HeartBeatService
{
        private CancellationToken _cancellationToken;
        private CancellationTokenSource _cancellationTokenSource;

        public void StartHeartBeatService(TimeSpan timeSpan)
        {
            _cancellationTokenSource = new CancellationTokenSource();
            _cancellationToken = _cancellationTokenSource.Token;
            Task.Run(async () =>
           {
               while (!_cancellationToken.IsCancellationRequested)
               {
                   SendHeartBeatToAzure();
                   try
                   {
                       await Task.Delay(timeSpan, _cancellationToken);
                   }
                   catch
                   {
                       break;
                   }
               }
           });
        }
        public void SuspendHeartBeatService()
        {
            _cancellationTokenSource?.Cancel();
        }

        private async void SendHeartBeatToAzure()
        {
            var platformService = ServiceLocator.Get<IPlatformService>();
            var location = await platformService?.GetPositionAsync();

            if (!double.IsNaN(location.Item1) && !double.IsNaN(location.Item2))
            {
                Debug.WriteLine($"Triggering Heartbeat with location{location.Item1},{location.Item2}");
                //TODO Invoke heartbeat api call.
            }
        }
    }

Код для отправки информации на сервер работает нормально.

Но есть проблема с CancellationToken , которая не работает / не отменяется. не уверен, что не так с реализацией.

1 Ответ

3 голосов
/ 29 апреля 2020

Измените сигнатуру SendHeartBeatToAzure, чтобы получить Task, чтобы ее можно было ожидать:

private async Task SendHeartBeatToAzure()

Затем await задача, возвращенная методом внутри l oop , Для достижения стабильного и последовательного пульса рекомендуется создать задачу Task.Delay перед вызовом метода:

Task.Run(async () =>
{
    while (true)
    {
        var delayTask = Task.Delay(timeSpan, _cancellationToken);
        await SendHeartBeatToAzure();
        await delayTask;
    }
});

В качестве примечания, вы, вероятно, должны хранить задачу, возвращаемую Task.Run как свойство только для чтения класса HeartBeatService, чтобы можно было отслеживать состояние задачи.

...