Разработка и Конфигурация · 11 мин
Как программно отменить поиск в 1С
Способы программной отмены поиска в 1С: остановка фоновых заданий, полнотекстового поиска, обработка прерывания пользователем. Примеры кода и проверка результата.
Задача программно отменить поиск в 1С возникает в нескольких ситуациях: пользователь запустил длительный фоновый поиск по данным и хочет его прервать, обновление полнотекстового индекса занимает ресурсы сервера, либо цикл поиска в коде нужно прервать по условию или по действию пользователя. Универсальной команды «отменить поиск» в платформе нет — механизм зависит от того, как именно поиск реализован.
Основные сценарии — это остановка фонового задания через объект ФоновыеЗадания, отмена длительной операции БСП методом ДлительныеОперации.ОтменитьВыполнениеЗадания, остановка обновления индекса полнотекстового поиска и корректное прерывание поискового цикла внутри собственного кода через ОбработкаПрерыванияПользователя. Ниже разобран каждый вариант с примерами.
Определите, какой именно поиск нужно отменить
Прежде чем писать код, важно понять природу поиска. Если поиск выполняется в фоновом задании (например, подбор товаров, поиск дублей, фоновая загрузка данных с поиском соответствий), отмена выполняется через менеджер фоновых заданий. Если поиск — это цикл внутри текущего сеанса, прервать его извне нельзя: нужно либо дать пользователю нажать Ctrl+Break, либо перенести логику в фон.
Отдельный случай — полнотекстовый поиск данных. Его обновление индекса выполняется регламентным заданием, и остановить его можно методами объекта ОперацииПолнотекстовогоПоиска. Наконец, если речь о поиске в динамическом списке или отборе в форме, «отмена» обычно означает сброс отбора, а не остановку процесса.
Как выбрать способ отмены
Отмена фонового задания поиска через ФоновыеЗадания
Если поиск запускается методом ФоновыеЗадания.Выполнить, платформа возвращает объект задания с уникальным идентификатором. Сохраните этот идентификатор — без него отменить задание программно не получится. Для отмены найдите задание по идентификатору и вызовите метод Отменить.
// Запуск поиска в фоне
Задание = ФоновыеЗадания.Выполнить("Обработки.ПоискДублей.МодульОбъекта.ВыполнитьПоиск",
ПараметрыПоиска, , "Поиск дублей контрагентов");
ИдентификаторЗадания = Задание.УникальныйИдентификатор;
// Отмена поиска
НайденноеЗадание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
Если НайденноеЗадание <> Неопределено
И НайденноеЗадание.Состояние = СостояниеФоновогоЗадания.Активно Тогда
НайденноеЗадание.Отменить();
КонецЕсли;
Метод Отменить работает как принудительное прерывание: задание завершается с состоянием «Отменено пользователем». Важно понимать, что отмена не откатывает уже выполненные изменения данных. Если поиск пишет промежуточные результаты в базу, продумайте транзакционность или очистку частичных результатов.
Отмена длительной операции в конфигурациях на БСП
В типовых конфигурациях на библиотеке стандартных подсистем длительный поиск обычно запускается через ДлительныеОперации.ВыполнитьВФоне или ДлительныеОперации.ВыполнитьФункцию. Для отмены предусмотрен отдельный метод, который корректно работает с инфраструктурой БСП.
&НаКлиенте
Процедура ОтменитьПоиск(Команда)
Если ЗначениеЗаполнено(ИдентификаторЗадания) Тогда
ОтменитьЗаданиеНаСервере(ИдентификаторЗадания);
ПоказатьОповещениеПользователя("Поиск отменён");
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ОтменитьЗаданиеНаСервере(ИдентификаторЗадания)
ДлительныеОперации.ОтменитьВыполнениеЗадания(ИдентификаторЗадания);
КонецПроцедуры
После отмены не забудьте отключить обработчик ожидания на клиенте (ОтключитьОбработчикОжидания), если форма периодически опрашивала состояние задания, и сбросить признак активности поиска — иначе интерфейс будет показывать «выполняется» при уже остановленном задании.
- 1Сохраните ИдентификаторЗадания при запуске поиска
- 2По команде пользователя вызовите ДлительныеОперации.ОтменитьВыполнениеЗадания()
- 3Отключите обработчик ожидания на клиенте
- 4Сбросьте признаки активности в форме и уведомите пользователя
- 5Проверьте состояние задания — оно должно перейти в ОтмененоПользователем
Остановка обновления полнотекстового поиска
Полнотекстовый поиск данных использует индекс, который обновляется регламентным заданием или вручную. Если обновление индекса грузит сервер, его можно остановить программно через объект ОперацииПолнотекстовогоПоиска.
// Проверка, идёт ли обновление индекса
Если ОперацииПолнотекстовогоПоиска.ПолучитьСостояниеОбновленияИндексаППД()
= СостояниеОбновленияИндексаППД.Выполняется Тогда
ОперацииПолнотекстовогоПоиска.ОстановитьОбновлениеИндексаППД();
КонецЕсли;
Учтите ограничения: выполнение этих методов требует права администрирования, а остановка обновления оставляет индекс частично актуальным — результаты полнотекстового поиска могут не содержать самых свежих данных. Если полнотекстовый поиск в базе не используется, его проще отключить целиком (УстановитьИспользованиеПолнотекстовогоПоиска(Ложь)), чем периодически останавливать обновление.
Прерывание поискового цикла в собственном коде
Когда поиск реализован циклом в текущем сеансе (обход выборки, перебор справочника), платформа не может прервать его извне — управление у пользователя «замораживается». Чтобы дать возможность отмены, вставьте в тело цикла вызов ОбработкаПрерыванияПользователя(). Тогда нажатие Ctrl+Break (в тонком клиенте — команда прерывания) остановит выполнение.
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ОбработкаПрерыванияПользователя();
// логика поиска
Если СовпадениеНайдено Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Для отмены по условию (нашли нужное, превышен лимит времени или число итераций) используйте обычный Прервать. Хорошая практика для длительных циклов — ограничивать максимальное время выполнения: фиксируйте ТекущаяДатаСеанса() до цикла и прерывайте его при превышении порога, чтобы поиск не работал бесконечно при ошибочных критериях.
Сброс поиска в форме списка и динамическом списке
Если под «отменой поиска» понимается сброс строки поиска в форме списка (например, пользователь ввёл текст в поле поиска, и его нужно очистить программно), механика другая. Поиск в динамическом списке реализуется через отбор, поэтому сброс — это удаление элемента отбора или очистка свойства СтрокаПоиска расширения формы динамического списка.
&НаКлиенте
Процедура СброситьПоиск(Команда)
Элементы.Список.СтрокаПоиска = "";
КонецПроцедуры
Для отбора, установленного программно через Список.Отбор или настройки компоновки, удалите соответствующий элемент отбора или сбросьте пользовательские настройки. После сброса список перечитается автоматически; если нет — вызовите Элементы.Список.Обновить().
Проверка результата и типичные проблемы
После программной отмены убедитесь, что задание действительно остановлено. Найдите его по идентификатору и проверьте свойство Состояние: ожидаемое значение — СостояниеФоновогоЗадания.ОтмененоПользователем. Если состояние осталось «Активно», отмена не сработала — например, из-за нехватки прав или потому что задание уже завершилось.
Отдельно проверьте журнал регистрации: при принудительной отмене там фиксируется событие отмены фонового задания. Это помогает отличить штатную отмену от аварийного завершения с ошибкой — внешне в интерфейсе они могут выглядеть одинаково.
Как проверить, что поиск остановлен
ОтмененоПользователем
Активно или Ошибка — отмена не применилась или задание упало само
Событие отмены задания без ошибок
Записи об ошибках в фоновом задании
Индикатор поиска скрыт, обработчик ожидания отключён
Форма продолжает показывать выполнение
Если отмена нужна регулярно и по бизнес-логике, а не как аварийная мера, лучше встроить «мягкую» отмену: фоновое задание периодически проверяет признак в хранилище или константе и завершается само, корректно закрывая транзакции. Это безопаснее принудительного Отменить().
Что важно запомнить
Способ отмены поиска зависит от его реализации: фоновое задание отменяется через ФоновыеЗадания или ДлительныеОперации, цикл в сеансе — через ОбработкаПрерыванияПользователя, обновление полнотекстового индекса — через ОперацииПолнотекстовогоПоиска, а поиск в списке сбрасывается очисткой строки поиска или отбора. Всегда проверяйте состояние задания после отмены.
Частые вопросы
Можно ли отменить чужое фоновое задание, запущенное другим пользователем?
Да, если у текущего пользователя есть административные права. Задание ищется через ФоновыеЗадания.НайтиПоУникальномуИдентификатору или ФоновыеЗадания.ПолучитьФоновыеЗадания с отбором, после чего вызывается Отменить(). Без административных прав доступны только собственные задания сеанса.
Почему Отменить() вызывает ошибку?
Чаще всего задание уже завершилось или не найдено по идентификатору. Перед отменой проверяйте, что объект задания не равен Неопределено и его состояние — Активно. Также ошибка возможна при недостатке прав.
Как прервать длительный цикл, если форма зависла и Ctrl+Break не помогает?
Если в цикле нет ОбработкаПрерыванияПользователя, платформа не обрабатывает прерывание — остаётся только завершить сеанс. Чтобы этого избежать, добавляйте вызов в тело любого потенциально долгого цикла или выносите поиск в фоновое задание.
Откатятся ли данные, записанные фоновым поиском до отмены?
Нет. Метод Отменить() не откатывает уже зафиксированные транзакции. Если это критично, проектируйте поиск как «только чтение» либо реализуйте мягкую отмену с контрольными точками и транзакционной записью.
Как полностью отключить полнотекстовый поиск, чтобы не останавливать обновление индекса?
Вызовите на сервере ОперацииПолнотекстовогоПоиска.УстановитьИспользованиеПолнотекстовогоПоиска(Ложь) с административными правами. После этого регламентное обновление индекса выполняться не будет, а поиск через полнотекстовый механизм станет недоступен.
Чем отличается Отменить() от мягкой остановки по флагу?
Отменить() прерывает задание принудительно в произвольной точке кода. Мягкая остановка — это когда задание само проверяет признак (например, значение в константе или хранилище) и завершается в контролируемом месте, корректно закрывая транзакции и освобождая ресурсы. Второй вариант безопаснее для заданий, изменяющих данные.