Завершить родительский метод из дочернего метода - PullRequest
0 голосов
/ 27 мая 2020

Создаю плагин для приложения. Когда пользователь нажимает команду остановки в родительском приложении, глобальная переменная, к которой имеет доступ мой плагин, принимает значение true. Для простого метода, который я создаю, я тестирую эту переменную и выхожу:

public class Status
{
    public static bool CheckTermFlag()
    {
        if (VoiceAttackPlugin._stopVariableToMonitor)
        {
            VoiceAttackPlugin._stopVariableToMonitor = false;
            return true;
        }
        return false;
    }
}

И я помещаю этот 'CheckTermFlag' в свой код:

class ForTesting
{
    public static void SendStopAllTest()
    {
        for (int i = 0; i <= 20; i++)
        {
            if (Status.CheckTermFlag())
            {
                return;
            }
            Thread.Sleep(500);
            vaProxy.WriteToLog(i.ToString(), "Green");
        }
    }

Проблема в том, что у меня может быть несколько методов, и каждый вызывает другой. Я не могу размещать вопрос для «Status.CheckTermFlag ()» на каждом этапе моей программы и распространять его вверх. вернуть при необходимости?

Ответы [ 2 ]

1 голос
/ 27 мая 2020

Почему бы не использовать для этого CancellationToken ? Таким образом вы можете остановить любой метод любым способом. Если у метода есть доступ к CTS, он может просто вызвать Cancel, и все методы с CancellationToken s могут затем завершить sh все, что они делают, и выйти.

В многопоточной среде a SemaphoreSlim может использоваться как ожидаемое событие сброса как средство синхронизации потоков.

Я бы не стал использовать Thread.Abort(), это хорошо для потоков, которые вы не контролируете. Но если это весь ваш код, и вы его контролируете - всегда лучше просто сигнализировать между потоками и вежливо попросить их завершить работу, что приведет к меньшему количеству неопределенных состояний и поведения позже.

Кстати, просто сделайте либо CancellationTokenSource доступным для методов, которые должны остановить вызывающий метод, или сделать доступным метод, вызывающий Cancel() на CTS. Я часто использовал этот подход в сетевом шлюзе с высокой нагрузкой и в настольном приложении, которое загружало большое количество файлов параллельно. Стоимость его ничтожна. Не бойтесь одноразовых материалов, при правильном использовании они экономят больше времени, чем требуется на обращение с ними.

0 голосов
/ 27 мая 2020

В многопоточном сценарии путь к go - это метод Thread.Abort(). Он выбрасывает ThreadAbortException в целевой поток, вызывая его завершение.

Если вам по какой-либо причине требуется специальное решение, сделайте то же самое. Вызывайте исключение и обрабатывайте его в самом верхнем методе, где это имеет смысл. Примерно так:

public class TerminateProcessingExeption : Exception { … }

…

public static bool CheckTermFlag()
{
    if (VoiceAttackPlugin._stopVariableToMonitor)
    {
        VoiceAttackPlugin._stopVariableToMonitor = false;
        throw new TerminateProcessingExeption();
    }
}

Кроме того, вместо флага bool рассмотрите возможность использования AutoResetEvent. См. Пример в документации для получения дополнительной информации. Простая переменная не защитит вас от неблагоприятных последствий одновременного доступа к памяти в многопроцессорных системах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...