В условиях реального производства часто возникает ситуация, которую можно назвать режимом «автомата Калашникова»: оператор стоит на линии и непрерывно сканирует штрихкоды, ожидая мгновенного выхода этикетки. Однако стандартные механизмы 1С часто не справляются с таким темпом. Проблема заключается в том, что формирование макета этикетки — процесс ресурсоемкий. Пока система занята рендерингом одного штрихкода, событие от COM-порта или сканера может быть проигнорировано, и «пики» уходят в пустоту. Разберем, как построить надежную архитектуру печати, которая не теряет ни одного задания.
Когда мы работаем напрямую через событие ВнешнееСобытие, 1С выполняет код последовательно. Если обработка одного сканирования (запрос к базе, формирование табличного документа, отправка на принтер) занимает 1–2 секунды, а оператор «пикает» три штрихкода за это же время, драйвер оборудования может не успеть передать данные в занятый поток 1С. Результат — пропуски в печати и недовольство персонала.
Первым делом нам необходимо развязать процесс сканирования и процесс печати. Сканер должен только фиксировать факт события, а печать — выполняться в фоновом режиме. Проанализируем реализацию этой схемы:
РегистрСведений.ОчередьПечатиЭтикеток.ВнешнееСобытие пропишем только одну быструю операцию — запись полученного штрихкода в этот регистр.РегламентныеЗадания, которые будут периодически опрашивать регистр и отправлять данные на печать.Чтобы избежать дублирования печати, когда несколько фоновых заданий пытаются обработать одну и ту же запись, воспользуемся механизмом блокировок и ресурсным флагом. Рассмотрим пример кода для обработки очереди:
Процедура ОбработатьОчередьПечати() Экспорт
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрСведений.ОчередьПечатиЭтикеток");
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
НачатьТранзакцию();
Попытка
Блокировка.Заблокировать();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 10
| Очередь.Штрихкод,
| Очередь.ПараметрыПечати
|ИЗ
| РегистрСведений.ОчередьПечатиЭтикеток КАК Очередь
|ГДЕ
| НЕ Очередь.ЗахваченоДляПечати
|УПОРЯДОЧИТЬ ПО
| Очередь.Период";
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Помечаем записи как захваченные
МенеджерЗаписи = РегистрыСведений.ОчередьПечатиЭтикеток.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Штрихкод = Выборка.Штрихкод;
МенеджерЗаписи.Прочитать();
Если МенеджерЗаписи.Выбран() Тогда
МенеджерЗаписи.ЗахваченоДляПечати = Истина;
МенеджерЗаписи.Записать();
КонецЕсли;
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
Возврат;
КонецПопытки;
// После фиксации транзакции выполняем длительную печать
// ... логика формирования макета и отправки на принтер ...
КонецПроцедуры
Важный момент: использование объекта БлокировкаДанных гарантирует, что второе фоновое задание не прочитает те же записи, пока первое их не пометит. Выбирая записи небольшими порциями (ВЫБРАТЬ ПЕРВЫЕ 10), мы обеспечиваем параллелизм и высокую скорость реакции системы.
Одной из главных причин тормозов является формирование ТабличныйДокумент. 1С тратит время на расчет шрифтов, отступов и генерацию графики. Промышленные принтеры этикеток (Zebra, TSC, Datamax) «понимают» специализированные языки разметки, такие как ZPL или TSPL.
Вместо передачи картинки, мы можем отправить в порт принтера простую текстовую строку. Выясним преимущества этого метода:
Пример формирования команды ZPL в коде 1С:
ТекстКоманды = "^XA
|^FO50,50^A0N,36,36^FDТовар: " + НаименованиеТовара + "^FS
|^FO50,100^BY3^BCN,100,Y,N,N^FD" + Штрихкод + "^FS
|^XZ";
// Отправка ТекстКоманды напрямую в COM-порт или через драйвер
Проанализируем еще один подход — объединение заданий. Если технологический процесс позволяет небольшую задержку (например, 5–10 секунд), можно накапливать отсканированные коды и печатать их не по одному, а одним общим документом. Это существенно снижает накладные расходы на инициализацию принтера и обращение к спулеру печати Windows. Как было отмечено в обсуждении, «плюнуть разом 50 этикеток» гораздо эффективнее, чем 50 раз по одной.
Если принтеров несколько, а физические COM-порты на сервере ограничены или работают нестабильно, целесообразно использовать преобразователи интерфейсов типа MOXA NPort. Это устройство позволяет вынести принтер в любую точку локальной сети и обращаться к нему по IP-адресу.
С точки зрения 1С, такой принтер все равно выглядит как COM-порт или сетевое устройство, но использование MOXA позволяет:
Для создания действительно надежной системы в режиме «нон-стоп» рекомендуем совместить подходы:
РегистрСведений как буфер для мгновенного приема данных от сканера.ФоновыеЗадания для обработки этого буфера, используя БлокировкаДанных для исключения дублей.Такая архитектура позволит вашим сотрудникам работать максимально быстро, не оглядываясь на «задумчивость» системы 1С.