Предотвращение перехвата рутинной ошибки вызывающего абонента в Visual Basic 6

#error-handling #vb6 #global-variables

#обработка ошибок #vb6 #глобальные переменные

Вопрос:

У меня ошибка, возникающая в моей программе Visual Basic 6 (первоначально написанной кем-то другим), где установлен (глобальный) флаг, который всегда должен быть сброшен до окончания процедуры. Иногда (редко, нерегулярно) это не так. Насколько я могу судить, он всегда будет сбрасываться в обычном потоке, просмотрев рассматриваемые подпрограммы.

Мое лучшее предположение о том, как этот флаг остается установленным, заключается в том, что в вызывающей функции (которых может быть много) происходит обработка ошибок, которая неправильно обрабатывает ошибку, возможно, с «Возобновить далее». Есть ли какой-либо способ, которым я могу помешать интересующему меня подразделу передать ошибку на более высокий уровень, а также показать мне строку, в которой произошла ошибка, и исходную ошибку? (Очевидно, я мог бы обернуть рассматриваемые подзаголовки в теги ошибок и получить подсказку msgbox, но это оставило бы меня довольно потерянным относительно того, где произошла фактическая ошибка)

Комментарии:

1. Почему бы не установить наблюдение за переменной для прерывания, если она изменяется, и вы находитесь в неправильном состоянии?

2. Это часто меняется, чтобы это было полезно — будет постоянно ломаться — и ошибка в этом не меняется.

3. Это единственная процедура, о которой вы говорите? Или несколько разных подпрограмм, которые используют одну и ту же настройку / сброс флага?

4. И не могли бы вы использовать «Break для всех ошибок»?

5. Существует 3 подпрограммы, которые устанавливают / сбрасывают флаг. Они вызываются из, я понятия не имею, скольких мест. Перерыв на все ошибки может сработать, попробую.

Ответ №1:

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

 Sub Routine_n()

    On Error GoTo ErrorHandler

    ... code ...

    g_bGlobalFlag = False

Exit Sub

ErrorHandler:
    g_bGlobalFlag = False
    Err.Raise Err.Number, Err.Source, Err.Description
End Sub
  

Обычная опасность добавления кода в обработчики ошибок заключается в том, что вы непреднамеренно сбрасываете объект Err. Ответом на это является сохранение свойств объекта Err во временных переменных и повторный вызов ошибки с использованием этих временных переменных. Однако в этом случае, поскольку установка логической переменной не может вызвать состояние ошибки, вполне разумно просто сбросить флаг перед повторным вызовом ошибки.

Комментарии:

1. Если бы мое предположение было верным, то это было бы (хакерским) решением проблемы. Однако, как это было, запуск с «Break on All» показал, что исключений, обработанных или иных, не было. Вместо этого проблема оказалась циклом тайм-аута с «DoEvents», который позволяет другой рутине прерывать работу без перехода. Удаление проклятых событий решило эту (и пару других) проблем

2. Ах! DoEvents — это зло!