Большая часть вашего вопроса, кажется, спрашивает, как выйти из непрерывного цикла в асинхронном контексте.Решение вашей проблемы - токены отмены .
. Простым примером может быть следующий:
class Caller
{
private CancellationTokenSource _cancellationTokenSource;
private Runner _runner;
public async Task StartAsync()
{
_cancellationTokenSource = new CancellationTokenSource();
try
{
_runner = new Runner();
await _runner.DoWorkAsync(_cancellationTokenSource.Token);
}
catch (OperationCanceledException) when (_cancellationTokenSource.IsCancellationRequested)
{
// this will ignore the exception when cancellation is requested. it might be useful in a reset scenario.
// otherwise, don't try/catch and just let the exception bubble up
}
finally
{
_runner = null;
_cancellationTokenSource = null;
}
}
public void Stop()
{
_cancellationTokenSource?.Cancel();
}
}
class Runner
{
public async Task DoWorkAsync(CancellationToken cancellationToken)
{
while(true)
{
cancellationToken.ThrowIfCancellationRequested();
await Task.Delay(TimeSpan.FromSeconds(30), cancellationToken);
}
}
}
StartAsync()
вызывающего абонента создаст CancellationTokenSource
,и запустите метод бегуна DoWorkAsync()
, передав ему токен отмены.
Метод DoWorkAsync()
вызывающей стороны будет на каждой итерации цикла запрашивать токен для исключения, если источник запросилотмена.Обратите внимание, что отмена совместная - вы должны проверить, была ли отмена запрошена, чтобы она работала.Вы также должны передать cancellationToken во все асинхронные методы, которые его принимают, как я продемонстрировал с помощью Task.Delay
.
Обратите внимание, что я использовал catch (OperationCanceledException) when (_cancellationTokenSource.IsCancellationRequested)
в методе StartAsync()
.Поскольку это сценарий сброса, я не хочу, чтобы исключение всплывало и вызывало сбой приложения, но я не хочу перехватывать подобные исключения, вызванные чем-то другим, кроме нашего запроса на отмену, отсюда и часть when ....
.То, как вы хотите справиться с этими вещами, зависит от вас, я просто решил, что продемонстрирую это одновременно, если это будет полезно в вашем сценарии.
Теперь, когда мы вызываем Stop()
, он просто помечаетзапрос отмены на токене, чтобы наш код совместной отмены знал, что пришло время отменить выполнение.