Прерывание длительных циклов


Я этот кусок кода, я хотел бы помочь. Я запустил длительный процесс, который я хочу прервать в любой момент. Дело в том, как вы можете видеть в коде, я если(остановка) везде, кроме методов внутри для (так как они имеют для петель тоже).

остановка - это переменная-член класса, а метод Stop() вызывается из UI из другого потока.

Я не думаю, что многопоточность будет хорошим вариантом так как будет более сложным, чтобы сохранить государство и общаться между потоками.

Можете вы придумать лучший способ решить это, делая чище код?

public void Start()
{
    for(int i = 0; i < Length; i++)
    {
        if(stop)
            return;

        LengthyMethodA();

        if(stop)
            return;

        LengthyMethodB();

        if(stop)
            return;

        LengthyMethodC();
    }
}

public void Stop()
{
    stop = true;
}


839
11
c#
задан 21 февраля 2011 в 03:02 Источник Поделиться
Комментарии
4 ответа

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

Что-то вроде :

List<Action> actions = new List<Action> {
() => LengthyMethodA(),
() => LengthyMethodB(),
() => LengthyMethodC() };

for(int i = 0; i < Length; i++)
{
foreach (Action action in actions)
{
action();
if(stop)
return;
}
}

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

8
ответ дан 21 февраля 2011 в 09:02 Источник Поделиться

Вы говорите, что начало работает в какой-нить другой, чем поток пользовательского интерфейса и стоп вызывается из UI-потока.

В таком случае, почему бы просто не вызвать прерывания в потоке, старт выполняется в? Это бросает исключение ThreadAbortException в начале потока и вызывает ваш код, чтобы провалиться, как вы предполагаете.

4
ответ дан 21 февраля 2011 в 05:02 Источник Поделиться

Любой конкретный ответ будет совершенно условной. Вы можете быть уверены, что остановка после шага B не будет иметь ужасающие последствия, связанные с тем, что шаг был успешно завершен? Я рекомендую вам разбить каждый раздел на работы, которые должны быть завершены возможность завершить перед входом. Тогда я рекомендую вам переключиться на AutoResetEvent , который является потокобезопасным. К сожалению, это действительно не приведет к меньше кода, но это сделает ваш код более надежным.

private readonly AutoResetEvent _stopRunning = new AutoResetEvent(false);

public void Start()
{
for(int i = 0; i < Length; i++)
{
if (_stopRunning.WaitOne(1)) return;
WorkThatMustRunToCompletion();
}
}

public void Stop()
{
_stopRunning.Set();
}

2
ответ дан 21 февраля 2011 в 04:02 Источник Поделиться

Похоже, пока вы не обращаетесь больше, чем эти три метода, что вы лучше, для ясности. И стоимость условные довольно дешево, насколько компиляция идет.

0
ответ дан 21 февраля 2011 в 10:02 Источник Поделиться