Есть ли способ «принудительно удалить» экземпляр из памяти, если он использует цикл while? - PullRequest
0 голосов
/ 15 октября 2018

Предположим, что у ClassX есть вечный цикл while.

Есть ли способ "принудительно остановить / удалить / очистить память" экземпляра ClassX?

или do У меня есть , чтобы вручную остановить цикл while в классе для GC?

1 Ответ

0 голосов
/ 15 октября 2018

Большая часть вашего вопроса, кажется, спрашивает, как выйти из непрерывного цикла в асинхронном контексте.Решение вашей проблемы - токены отмены .

. Простым примером может быть следующий:

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(), он просто помечаетзапрос отмены на токене, чтобы наш код совместной отмены знал, что пришло время отменить выполнение.

...