Как правильно организовать проведение документа в фоновом режиме в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Проведение тяжелых документов в фоновом режиме — это распространенная задача, когда требуется повысить отзывчивость интерфейса для пользователя — её решает обработка для ускорения группового проведения документов. Однако при реализации этой функции разработчики часто сталкиваются с тем, что фоновое задание «не видит» данные нового документа или видит старые данные существующего. Фоновые задания для новичков могут вызвать вопросы, поэтому в этой статье мы детально проанализируем причины этой проблемы и разберем наиболее надежные способы реализации фонового проведения.

Проблема изоляции транзакций: почему фоновое задание «не видит» ссылку

Рассмотрим стандартную ситуацию: разработчик пытается запустить фоновое задание непосредственно из процедуры ОбработкаПроведения. На первый взгляд, логика верна: документ уже записывается, ссылка у него есть. Однако при попытке прочитать данные в фоновом сеансе система выдает ошибку «Объект не найден» или считывает пустые таблицы.

Выясним причину: всё дело в механизме изоляции транзакций в СУБД (уровень Read Committed). Если мы анализируем SQL сервер глазами 1С-ника, то увидим, что когда выполняется процедура ОбработкаПроведения, транзакция записи документа еще не завершена. Фоновое задание запускается в отдельном сеансе и в своей собственной транзакции. Согласно правилам СУБД, одна транзакция не может видеть незафиксированные изменения другой транзакции. Это защищает систему от «грязного чтения» — ситуации, когда фоновый процесс обработал бы данные документа, а основная транзакция в итоге завершилась бы ошибкой и откатилась.

Проанализируем пример кода, который часто приводит к ошибке (кстати, Консоль кода + ИИ-помощник поможет быстрее писать такие алгоритмы — см. инструмент разработчика с консолью кода и ИИ-помощником):


Процедура ОбработкаПроведения(Отказ, РежимПроведения)
    // ОШИБКА: Транзакция еще не зафиксирована!
    ДлительнаяОперация = НачатьПроведениеДокументаВФоне(Ссылка); 
КонецПроцедуры

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

Решение №1: Использование очереди в Регистре сведений (Рекомендуемое)

Наиболее надежный и масштабируемый способ — это реализация механизма отложенного проведения через вспомогательный объект или полноценный Конвейер обработки задач. Рассмотрим по шагам, как это реализовать:

  1. Создадим непериодический Регистр сведений ОчередьОтложенногоПроведения.
  2. Добавим в него измерения: Документ (тип Ссылка) и ресурсы: ДатаПостановки, Статус (Перечисление: В очереди, Выполняется, Ошибка).
  3. В процедуре модуля документа ПриЗаписи (или в форме) будем добавлять запись в этот регистр.

Посмотрим на пример кода добавления в очередь:


Процедура ПриЗаписи(Отказ)
    Если ДополнительныеСвойства.Свойство("ПроводитьВФоне") Тогда
        МенеджерЗаписи = РегистрыСведений.ОчередьОтложенногоПроведения.СоздатьМенеджерЗаписи();
        МенеджерЗаписи.Документ = Ссылка;
        МенеджерЗаписи.ДатаПостановки = ТекущаяДата();
        МенеджерЗаписи.Статус = Перечисления.СтатусыЗаданий.ВТрафике;
        МенеджерЗаписи.Записать();
    КонецЕсли;
КонецПроцедуры

Затем создадим регламентное задание, которое будет раз в минуту выбирать записи из этого регистра со статусом «В очереди» и выполнять ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение). Это гарантирует, что к моменту начала работы регламентного задания транзакция записи документа уже точно будет завершена.

Решение №2: Запуск фонового задания из формы после записи

Если нам нужно запустить проведение интерактивно и только для одного конкретного документа, можно воспользоваться событием формы ПослеЗаписиНаСервере. В этот момент основная транзакция записи уже завершена, и данные доступны для других сеансов.

Разберем алгоритм работы в форме:


&НаСервере
Процедура ПослеЗаписиНаСервере(ТекущийОбъект, ПараметрыЗаписи)
    // Здесь транзакция уже завершена. Можно запускать фон.
    ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
    ПараметрыВыполнения.НаименованиеФоновогоЗадания = "Проведение документа в фоне";
    
    ИмяМетода = "МодульМенеджераДокумента.ВыполнитьПроведение";
    ДлительныеОперации.ВыполнитьПроцедуру(ПараметрыВыполнения, ИмяМетода, ТекущийОбъект.Ссылка);
КонецПроцедуры

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

Решение №3: Использование механизмов БСП «Очередь заданий»

Если в вашей конфигурации используется «Библиотека стандартных подсистем» (БСП), лучше не изобретать велосипед, а использовать готовую подсистему «Очередь заданий». Это более профессиональный подход, который решает проблемы отказоустойчивости.

Основные преимущества использования очереди БСП:

Технические нюансы и «подводные камни»

Проанализируем несколько критических моментов, о которых часто забывают:

1. Контроль актуальности данных. Пока документ проводится в фоне, пользователь может открыть его и нажать «Провести» еще раз. В результате может возникнуть коллизия. Рекомендуется при постановке в очередь устанавливать у документа статус (реквизит) «Проводится», и запрещать его редактирование на уровне формы, пока статус не сменится на «Проведен».

2. Передача параметров. Если логика проведения зависит от настроек на форме, которые не сохраняются в реквизиты документа, передавайте их через ВременноеХранилище. Но помните, что адрес временного хранилища должен быть доступен для фонового сеанса (используйте идентификатор формы или ПоместитьВоВременноеХранилище с передачей управления фоновому заданию).

3. Использование пауз (костыльное решение). В обсуждении упоминался вариант поставить Паузу в начале фонового задания на 5-10 секунд. Мы крайне не рекомендуем этот способ. Это неоправданная трата ресурсов сервера, которая не дает 100% гарантии: при высокой нагрузке транзакция может длиться дольше, чем ваша пауза.

4. Обработка ошибок. Если фоновое проведение завершилось с ошибкой (например, не хватило остатков), пользователь должен об этом узнать. При использовании регистра очереди обязательно добавляйте строковое поле ТекстОшибки, чтобы выводить его пользователю при следующем открытии документа.

Резюмируем: для стабильной работы системы всегда разделяйте процесс фиксации данных документа и процесс его фоновой обработки. Используйте промежуточное хранилище (регистр сведений) или штатные механизмы очередей заданий БСП.

← На главную