Как реализовать параллельную печать чеков на нескольких ККМ в 1С

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

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

Проблема: Почему стандартные методы 1С не обеспечивают параллелизм?

Рассмотрим стандартную ситуацию: у нас есть несколько ККМ, подключенных к одному рабочему месту. При попытке вызвать методы печати в цикле, 1С ожидает завершения каждой операции. Попытки использовать методы Оповестить() или ВыполнитьОбработчикОповещения() не приносят результата, так как они лишь передают управление внутри того же самого основного потока интерфейса. Пока драйвер занят передачей данных в порт ККТ, интерфейс «зависает», и следующий вызов ждет своей очереди.

Механизм фоновых заданий в 1С реализован на стороне сервера. В файловом варианте или при необходимости прямого доступа к локальным портам (COM/USB) через клиентское приложение, серверные задания не могут напрямую «дотянуться» до драйвера, установленного на конкретном ПК пользователя без сложных дополнительных прослоек.

Решение 1: Использование внешнего HTTP-сервиса (KkmServer)

Проанализируем наиболее стабильный промышленный подход — использование специализированного ПО, такого как KkmServer или аналогичных решений. Суть метода заключается в выносе логики управления оборудованием за пределы 1С.

Алгоритм работы выглядит следующим образом:

  1. На компьютере, к которому подключены кассы, устанавливается служба (Windows Service), которая сама умеет работать с драйверами.
  2. 1С не обращается к драйверу напрямую. Вместо этого мы формируем HTTPСоединение и отправляем JSON-пакет с данными чека на локальный адрес сервиса (например, http://localhost:5893).
  3. Поскольку HTTP-запрос в 1С можно выполнить асинхронно или очень быстро (сервис просто ставит задачу в свою внутреннюю очередь и сразу возвращает ответ «Принято»), основной поток 1С освобождается мгновенно.

Пример формирования запроса в 1С:


Соединение = Новый HTTPСоединение("localhost", 5893);
Запрос = Новый HTTPЗапрос("/Execute/PrintCheque");
Запрос.УстановитьТелоИзСтроки(ДанныеЧекаВФорматеJSON);
// Отправляем и не ждем физического окончания печати ленты
Ответ = Соединение.ОтправитьДляОбработки(Запрос);

Решение 2: Использование Web-сервера драйвера АТОЛ (ДТО 10)

Если вы используете современное оборудование АТОЛ и драйверы 10-й версии, разберем встроенную возможность — Web-сервер АТОЛ. Производитель уже заложил механизм управления очередью печати через HTTP/JSON.

Выясним причину, почему это эффективно: при такой архитектуре 1С общается не с COM-объектом драйвера, который блокирует поток, а с сетевым интерфейсом. Это позволяет отправлять команды на разные кассы (идентифицируемые по ID или серийному номеру) практически одновременно. Драйвер сам распределяет потоки данных по портам.

Решение 3: Собственный диспетчер печати (Файловая очередь)

Если готовые платные решения не подходят, рассмотрим вариант реализации собственного «сервиса-прокладки», как это сделал автор обсуждаемой темы. Этот способ отлично подходит для 1С программистов, владеющих дополнительными языками программирования (C++, C#, Python).

Логика системы строится на отложенной обработке:

  1. В 1С вместо печати мы пишем процедуру, которая выгружает данные чека в определенный формат (XML или JSON) и сохраняет их в специальную папку на диске.
  2. Параллельно в Windows запущен сервис (написанный, например, на C++), который «мониторит» эту папку.
  3. Как только появляется новый файл, сервис считывает его, создает отдельный системный поток (Thread) и через Native API или COM-объект драйвера отправляет данные на конкретную ККТ.

Рассмотрим пример кода 1С для такой выгрузки:


Процедура ОтправитьНаПечатьПараллельно(ДанныеЧека)
    ИмяФайла = "C:\PrintQueue\" + Строка(Новый УникальныйИдентификатор) + ".json";
    ЗаписьJSON = Новый ЗаписьJSON;
    ЗаписьJSON.ОткрытьФайл(ИмяФайла);
    ЗаписатьJSON(ЗаписьJSON, ДанныеЧека);
    ЗаписьJSON.Закрыть();
    // 1С свободна, сервис подхватит файл и напечатает его в фоне
КонецПроцедуры

Решение 4: Асинхронные вызовы в платформе 8.3.18+

Посмотрим на возможности современных версий платформы. Использование директивы &Асинхрон и оператора Ждать позволяет реализовать неблокирующий интерфейс. Хотя это не является честной многопоточностью (код всё равно выполняется поочередно в одном потоке приложения), использование асинхронных методов работы с внешними компонентами позволяет кассиру продолжать работу с формой, пока драйвер обрабатывает команду в фоновом режиме платформы.

Важные рекомендации по реализации

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

Проанализировав ситуацию, можно сделать вывод: наиболее надежным и масштабируемым способом является переход на HTTP-взаимодействие с кассовым оборудованием, так как это штатно позволяет реализовать асинхронность и параллелизм, недоступные при прямом использовании старых COM-компонент в рамках одного сеанса 1С.

← На главную