Фоновые задания в 1С позволяют выполнять долгие операции асинхронно и не блокировать интерфейс пользователя. В администрировании 1С на вкладке «Регламентные и фоновые задания» отображается список заданий с колонками «Состояние», «Начало» и «Окончание». В этом списке видно состояние каждой задачи, время ее запуска и завершения. При этом фоновые задачи обычно порождаются планировщиком по расписанию регламентных операций – каждый запуск регламентного задания создает новое фоновое задание, которое выполняет нужную процедуру. Например, можно поставить задачу на отправку почты по списку адресов, и она будет выполняться в фоновом режиме, пока вы продолжаете работать с программой.
- Фоновые задания в 1С 8
- Как запустить выполнение метода программного кода в фоновом задании
- Как остановить фоновое задание по истечении времени
- Как «снять» фоновое задание
- Как найти зависшие фоновые задания 1С
- Как поставить на паузу фоновое задание 1С
- Пример запуска фонового задания
- Отладка фонового задания не в фоне
- Программный код для поиска и остановки фонового задания
- Заключение
Фоновые задания в 1С 8
В платформе 1С (версии 8.x) фоновые задания создаются через глобальный объект МенеджерФоновыхЗаданий, к которому можно обратиться через синоним ФоновыеЗадания. Запустить фоновую задачу просто: вызовите метод Выполнить этого менеджера, передав имя общего модуля и экспортируемой процедуры (в формате "Модуль.ИмяПроцедуры"). Фоновые задания запускаются только на сервере и выполняются в отдельных потоках. При этом каждое задание – это отдельный сеанс от имени пользователя, который его создал. В файловом режиме одновременно выполняется только одно фоновое задание, остальные станут в очередь. В клиент-серверном режиме задания распределяются по наименее загруженным рабочим процессам сервера. Для предотвращения дублирования можно использовать параметр «Ключ»: если задать один и тот же ключ, повторный запуск такого же задания вызовет ошибку "Задание с таким ключом уже выполняется". При необходимости в метод Выполнить можно передать массив параметров, которые будут переданы экспортной процедуре фонового задания. Метод Выполнить возвращает объект фонового задания, у которого есть свойства Состояние (активно, завершено, ошибкой или отменено) и ИнформацияОбОшибке, а также методы для управления (отмена, ожидание). Например, можно получить объект в переменную, вызвать ОжидатьЗавершенияВыполнения() и затем проверить Состояние, чтобы узнать результат.
Как запустить выполнение метода программного кода в фоновом задании
Если искомый метод находится в общем модуле, он должен быть экспортным. И запустить его можно с помощью такой строки:
ФоновыеЗадания.Выполнить("мсФоновоеВыполнениеИнтеграция.ПроверитьУстановитьОбновления");
Если это метод внешней обработки, ситуаций сложнее. Код для конфигураций со встроенным БСП будет выглядеть следующим образом:
ПараметрыВыполненияОбработки = Новый Структура; ПараметрыВыполненияОбработки.Вставить("НомерФоновогоЗадания", НомерПотока); ПараметрыВыполненияОбработки.Вставить("КоличествоФоновыхЗаданий", КоличествоПотоков); ПараметрыВыполненияОбработки.Вставить("АдресТаблицыВХранилище", АдресТаблицы); ПараметрыВыполненияОбработки.Вставить("АдресСтруктурыКоманд", АдресСтруктуры); ПараметрыВыполненияОбработки.Вставить("ДатаСверткиИБ", Объект.ДатаСверткиИБ); ЭтоВнешняяОбработка = ЭтоВнешняяОбработка(); ИмяОбработки = ?(ЭтоВнешняяОбработка, ХранениеФайлаОбработки, РеквизитФормыВЗначение("Объект").Метаданные().ПолноеИмя()); ПараметрыЗадания = Новый Структура; ПараметрыЗадания.Вставить("ИмяОбработки", ИмяОбработки); ПараметрыЗадания.Вставить("ИмяМетода", "ОбработкаДанныхВФоне"); ПараметрыЗадания.Вставить("ПараметрыВыполнения", ПараметрыВыполненияОбработки); ПараметрыЗадания.Вставить("ЭтоВнешняяОбработка", ЭтоВнешняяОбработка); ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор); ПараметрыВыполнения.НаименованиеФоновогоЗадания = НСтр("ru = 'Свертка базы данных 1С'"); ПараметрыВыполнения.ЗапуститьВФоне = Истина; ПараметрыВыполнения.Вставить("ИдентификаторФормы", УникальныйИдентификатор); ВыполняемыйМетод = "ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки"; // Выполняем процедуру из модуля объекта Возврат ДлительныеОперации.ВыполнитьВФоне(ВыполняемыйМетод, ПараметрыЗадания, ПараметрыВыполнения);
Как остановить фоновое задание по истечении времени
Если фоновое задание должно завершиться по таймауту, можно использовать метод ожидания с таймаутом и затем отменить задание, если оно все еще активно. В версии 8.3.13+ появился метод ОжидатьЗавершенияВыполнения(Таймаут) как у объекта ФоновоеЗадание, так и у менеджера ФоновыеЗадания. Например, после старта можно вызвать ФЗ.ОжидатьЗавершенияВыполнения(секунд). Если по истечении этого времени задание еще не завершено (состояние «Активно»), то можно вызвать ФЗ.Отменить(). Примерный алгоритм:
- Запустить фоновую задачу и сохранить объект или его идентификатор.
- Через заданный интервал времени получить задание (методом поиска по ID) и проверить его
Состояние. - Если состояние все еще «Активно», вызвать
Отменить(), чтобы остановить выполнение.
При отсутствии метода таймаута можно написать циклическое ожидание: в цикле проверять, не превысило ли время выполнения предел, и вызывать Отменить() при необходимости. Важно отметить, что досрочная отмена фонового задания возбудит исключение в самой задаче – его можно отловить внутри, если нужно выполнить какие-то действия при прерывании.
Как «снять» фоновое задание
Часто под «снять» понимают отмену или удаление фонового задания. Простейший способ – программно отменить его методами 1С: найти по уникальному идентификатору и вызвать Отменить(). Например:
&НаСервере Процедура ОстановитьФЗ(УИ_Задания) Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(УИ_Задания); Если Задание <> Неопределено Тогда Задание.Отменить(); КонецЕсли; КонецПроцедуры
Если нужно отключить выполнение регламентного задания (которое порождает фоновое), можно снять флажок «Включено» в окне настроек регламентных заданий. А если фоновое задание зависло и не реагирует на штатные методы, можно воспользоваться консолью кластера: пометить процесс с зависшей задачей неактивным, найти его PID и убить процесс rphost.exe – после этого сессия фонового задания завершится принудительно. Этот способ экстренный и требует прав администратора сервера.
Как найти зависшие фоновые задания 1С
Зависшими обычно называют задания в состоянии «Активно», которые выполняются слишком долго. Чтобы их найти, можно получить список текущих фоновых заданий и отфильтровать по статусу и времени начала. Например, в коде 1С есть метод ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор), который вернет список объектов заданий. Пример:
Отбор = Новый Структура; Отбор.Вставить("Состояние", СостояниеФоновогоЗадания.Активно); ФЗ_Активные = ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор); Для Каждого ФЗ Из ФЗ_Активные Цикл Если (ТекущаяДата() - ФЗ.Начало) * 24 * 60 > МаксимальноеВремяMin Тогда // задача выполняется дольше допустимого ФЗ.Отменить(); КонецЕсли; КонецЦикла
Здесь Отбор – структура с условиями для метода ПолучитьФоновыеЗадания. В ней можно указать, например, "Состояние"=СостояниеФоновогоЗадания.Активно, чтобы получить только активные задания. Кроме этого можно фильтровать по дате начала или имени метода. После получения списка перебираем каждое задание, сравниваем его Начало с текущей датой и при превышении порога вызываем Отменить(). Так мы получаем «зависшие» задания и снимаем их.
Как поставить на паузу фоновое задание 1С
В платформе 1С нет прямого метода «Пауза» фонового задания, но можно эмулировать паузу с помощью ожидания. Один из подходов – создать процедуру, которая в клиентском сеансе запускает фоновое задание, ждет заданное время, а в фоновой сессии просто «усыпляет» себя до истечения таймаута. В примере ниже общий модуль содержит процедуру Пауза(Таймаут):
&НаСервере Процедура Пауза(Секунды) Экспорт ТекСеанс = ПолучитьТекущийСеансИнформационнойБазы(); ФЗ = ТекСеанс.ПолучитьФоновоеЗадание(); Если ФЗ = Неопределено Тогда // Если мы в клиенте, запускаем фоновое задание для паузы Парам = Новый Массив; Парам.Добавить(Секунды); ФЗ = ФоновыеЗадания.Выполнить("МодульФЗ.Пауза", Парам); КонецЕсли; // Ждем истечения времени или завершения фонового задания ФЗ.ОжидатьЗавершенияВыполнения(Секунды); КонецПроцедуры
В этом коде сначала определяется, находится ли мы в сеансе фонового задания: если нет, создаем новый фоновой запуск того же метода Пауза с таймаутом в секундах. Фоновое задание, получив параметр, просто ждет переданной секунды через метод ожидания ОжидатьЗавершенияВыполнения(Секунды). Таким образом достигается эффект «паузы» без загрузки процессора. Вызывать паузу просто: МодульФЗ.Пауза(5) для 5 секунд задержки. Этот способ удобен, когда нужна не активная загрузка процессора, а именно пауза в выполнении.
Пример запуска фонового задания
Запустить фоновое задание можно одним вызовом ФоновыеЗадания.Выполнить. Вот упрощенный пример кода запуска из клиентской подсистемы или формы (на сервере):
<pre><code> &НаСервере Процедура ЗапуститьРассылкуЭлектронныхПисем() ИмяМетода = "ОбщийМодульОтправкиЭлектронных.ПровестиРассылку"; Ключ = "РассылкаПисем"; // чтобы избежать повторного запуска одного и того же задания // Подготовим параметры (например, список адресов и тело письма) Парам = Новый Массив; Парам.Добавить(СписокАдресов); Парам.Добавить(ТелоПисьма); // Запускаем задание ФЗ = ФоновыеЗадания.Выполнить(ИмяМетода, Парам, Ключ); // По желанию можно получить идентификатор или сразу ждать завершения УИД = ФЗ.УникальныйИдентификатор; КонецПроцедуры
В этом примере мы формируем ИмяМетода с полным именем экспортной процедуры модуля, готовим массив параметров и вызываем ФоновыеЗадания.Выполнить. Третий параметр – ключ задачи – помогает отличать несколько одинаковых заданий. Метод возвращает объект задачи, у которого можно запросить УникальныйИдентификатор или сразу вызвать ОжидатьЗавершенияВыполнения, если нужно дождаться результата.
Отладка фонового задания не в фоне
Отладка фоновых заданий затруднена, поскольку они выполняются в отдельном потоке. Есть два основных подхода. Во-первых, в режиме отладки можно включить автоматическое подключение фоновых заданий («Автоподключение», опция «Фоновые задания»), тогда IDE будет подключаться к сеансам фоновых задач. Но при многочисленных задачах это часто ведет к «дерганным» окнам и перегрузке системы. Второй способ – выполнять задание в синхронном режиме. Если задача запускается через БСП (например, метод ДлительныеОперации.ЗапуститьВыполнениеВФоне), то в конфигураторе можно включить опцию «Запускать фоновые задания без фонового режима». Тогда все фоновые вызовы будут выполняться прямо в основном сеансе, позволяя полноценно шагать через код. В итоге получается обычный вызов процедуры – и отладку делать в привычном режиме. После налаживания можно вернуть фоновые задачи в асинхронный режим.
Программный код для поиска и остановки фонового задания
Ниже приведены примеры наиболее часто используемого кода для работы с фоновыми заданиями:
- Поиск по ID и остановка задания: найти задание по уникальному идентификатору и вызвать
Отменить():Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания); Если Задание <> Неопределено Тогда Задание.Отменить(); КонецЕсли;
- Поиск зависших задач: получить все активные фоновые задания и отменить те, что выполняются дольше заданного времени:
Отбор = Новый Структура("Состояние", СостояниеФоновогоЗадания.Активно); Задачи = ФоновыеЗадания.ПолучитьФоновыеЗадания(Отбор); Для Каждого ФЗ Из Задачи Цикл Если (ТекущаяДата() - ФЗ.Начало) * 24 * 60 > ЛимитМинут Тогда ФЗ.Отменить(); КонецЕсли; КонецЦикла;
- Ожидание завершения нескольких задач: собрать задания в массив и дождаться их завершения:
(метод
МассивЗаданий = Новый Массив; МассивЗаданий.Добавить(ФоновыеЗадания.Выполнить(...)); МассивЗаданий.Добавить(ФоновыеЗадания.Выполнить(...)); ФоновыеЗадания.ОжидатьЗавершения(МассивЗаданий);
ОжидатьЗавершенияблокирует текущий поток, пока все задачи из массива не завершатся).
Приведенный код иллюстрирует основные приемы. В зависимости от ситуации можно комбинировать фильтрацию (ПолучитьФоновыеЗадания(Отбор)) и прямую загрузку фонового задания (Выполнить и Отменить()). Важно учитывать, что отмена фонового задания может приводить к исключениям внутри кода задачи, поэтому по возможности следует обрабатывать или предвидеть такую ситуацию.
Ниже еще один пример программного кода для остановки фонового задания, запущенного отдельным методом:
СтруктураОтбора = Новый Структура("ИмяМетода, Состояние", "ТутИмяМетодаРанееЗапущенногоВамиВФоновомЗадании", СостояниеФоновогоЗадания.Активно); Массив = ФоновыеЗадания.ПолучитьФоновыеЗадания(СтруктураОтбора); Для Каждого ФоновоеЗадание Из Массив Цикл ФоновоеЗадание.Отменить(); Сообщить("Нашли и отменили фоновое задание"); КонецЦикла;
Заключение
Работа с фоновыми заданиями 1С требует понимания их особенностей: они выполняются в отдельных сессиях на сервере и могут быть найдены и остановлены через API МенеджераФоновыхЗаданий. Из описанных методов чаще всего наиболее удобен программный контроль: через ФоновыеЗадания.ПолучитьФоновыеЗадания и НайтиПоУникальномуИдентификатору можно искать нужные задания по состоянию или ID, а затем вызывать Отменить(), чтобы прервать долгую операцию. Для отладки стоит запускать задачу без фонового режима (синхронно) или использовать встроенный дебаггер с автоподключением. Если же задание повисло без возможности завершиться, то крайний метод – прекратить соответствующий процесс сервера. Выбор метода зависит от конкретной задачи: программный контроль через API гибок и автоматизируем, тогда как ручная отмена через консоль применяется лишь в экстремальных случаях.
В завершение предлагаем читателям подписаться на нашу рассылку и посмотреть другие статьи на эту тему. Если у вас остались вопросы или нужен совет по фоновой обработке в 1С, задайте их нашей команде – мы всегда рады помочь разобраться в тонкостях платформы!














































