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

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

Разработка под мобильную платформу 1С имеет ряд специфических ограничений, с которыми разработчики часто сталкиваются при попытке перенести логику фоновых процессов из настольных и клиент-серверных решений. Нередко возникает ситуация, когда фоновые задания стартуют с большой задержкой (от 30 секунд до нескольких минут), накапливаются в очередь и затем отрабатывают разом («пачкой»), либо приводят к нестабильной работе приложения.

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

Особенности и ограничения фоновых заданий на мобильной платформе

Проанализируем ключевые архитектурные отличия мобильной платформы 1С от настольной версии:

  1. Строгая последовательность выполнения (однозадачность): на мобильной платформе фоновые задания не могут выполняться параллельно. В каждый момент времени обрабатывается строго одно фоновое задание. Регламентные задания по расписанию не поддерживаются — запуск возможен только программно через метод ФоновыеЗадания.Выполнить.
  2. Отложенная инициализация планировщика: менеджер фоновых заданий мобильной платформы инициализируется не в момент старта приложения, а при первом вызове фонового метода. Из-за этого первый запуск фонового задания может происходить с паузой от нескольких секунд до минуты.
  3. Ограничения мобильных ОС (Android / iOS): при блокировке экрана или сворачивании приложения мобильная операционная система замораживает сетевые сокеты и вычислительные потоки программы для экономии заряда батареи. Если пользователь запускает обмен и блокирует экран, задание приостанавливается. При возврате в приложение накопленная очередь задач резко активизируется и начинает отрабатывать подряд.
  4. Зависание при повторном запуске: если запустить фоновое задание, пока предыдущее еще находится в состоянии СостояниеФоновогоЗадания.Активно, система ставит задачу в очередь либо может завершиться аварийно при некорректной очистке ресурсов.

Пример реализации запуска фонового задания и отслеживания прогресса

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

Разберем серверную процедуру запуска фонового задания:


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

На клиенте по нажатию команды подключаем обработчик ожидания и передаем управление серверу для создания задачи:


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

В процедуре фонового обмена (например, в общем модуле с признаком вызова на сервере) выполняется длительная работа и регистрируются пользовательские сообщения:


Процедура ВыполнитьОбменДанными(Товар) Экспорт
    
    // В цикле обработки данных формируем сообщения о проценте выполнения
    Для Индекс = 1 По 100 Цикл
        
        // Выполнение полезной работы (HTTP-запрос, запись данных)
        // ...
        
        СообщениеПользователю = Новый СообщениеПользователю;
        СообщениеПользователю.Текст = "Загружено " + Строка(Индекс) + " %";
        СообщениеПользователю.Сообщить();
        
    КонецЦикла;
    
КонецПроцедуры

Для чтения прогресса напишем функцию опроса состояния фонового задания на сервере с использованием метода ПолучитьСообщенияПользователю:


&НаСервере
Функция ПолучитьСообщенияИзФоновогоЗадания(ИмяПроцедуры, УИДЗадания)
    
    Ответ = Новый Структура;
    Ответ.Вставить("Результат", "ВПроцессе");
    Ответ.Вставить("Сообщения", Новый Массив);
    
    СтруктураОтбора = Новый Структура;
    СтруктураОтбора.Вставить("ИмяМетода", ИмяПроцедуры);
    СтруктураОтбора.Вставить("Ключ", УИДЗадания);
    
    МассивЗаданий = ФоновыеЗадания.ПолучитьФоновыеЗадания(СтруктураОтбора);
    
    Если МассивЗаданий.Количество() > 0 Тогда
        ТекЗадание = МассивЗаданий[0];
        
        Если ТекЗадание.Состояние <> СостояниеФоновогоЗадания.Активно Тогда
            Ответ.Результат = "Завершено";
        КонецЕсли;
        
        // Считываем сообщения с удалением прочитанных (параметр Истина)
        Ответ.Сообщения = ТекЗадание.ПолучитьСообщенияПользователю(Истина);
    КонецЕсли;
    
    Возврат Ответ;
    
КонецФункции

Клиентский обработчик ожидания принимает накопленные сообщения, отображает последнее состояние пользователю и отключает таймер при завершении задачи:


&НаКлиенте
Процедура ОбработчикОжидания_СообщенияПользователю() Экспорт
    
    Ответ = ПолучитьСообщенияИзФоновогоЗадания("ОбщийМодульСервер.ВыполнитьОбменДанными", УИДЗадания);
    МассивСообщений = Ответ.Сообщения;
    
    Если МассивСообщений.Количество() > 0 Тогда
        ОчиститьСообщения();
        ТекстСообщения = "Загрузка данных: " + МассивСообщений[МассивСообщений.Количество() - 1].Текст;
        Сообщить(ТекстСообщения);
    КонецЕсли;
    
    Если Ответ.Результат = "Завершено" Тогда
        ОчиститьСообщения();
        Сообщить("Загрузка данных успешно завершена.");
        ОтключитьОбработчикОжидания("ОбработчикОжидания_СообщенияПользователю");
    КонецЕсли;
    
КонецПроцедуры

Рекомендации по стабильной работе фоновых процессов

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

  1. Контроль активных заданий перед стартом: перед вызовом нового задания всегда проверяем, не выполняется ли уже задача с помощью метода ФоновыеЗадания.ПолучитьФоновыеЗадания. Не допускайте запуска нескольких фоновых процессов одновременно.
  2. Явные таймауты сети: при выполнении сетевых операций через объект HTTPСоединение обязательно указывайте явный параметр Таймаут. При потере мобильной связи фоновое задание без таймаута надолго останется в активном состоянии и заблокирует запуск последующих задач.
  3. Объединение мелких операций в одну процедуру: вместо частых запусков мелких фоновых заданий формируйте один общий серверный вызов, передавая в него сразу весь массив объектов или групп для обработки.
  4. Синхронная порционная загрузка как альтернатива: если фоновые задания на целевой сборке платформы работают нестабильно, можно разбить длительный процесс на порции и выполнять их синхронно через клиентские вызовы с обновлением интерфейса между итерациями.
← На главную