При работе с большим количеством кассовых аппаратов в 1С (особенно в файловых базах типа «1С:Розница») программисты часто сталкиваются с проблемой последовательного выполнения кода. Стандартная логика работы драйверов торгового оборудования такова, что пока один чек не закончит печататься, управление не возвращается в систему, и печать на втором аппарате не начинается. В этой статье мы подробно разберем, как обойти ограничение однопоточности клиентского приложения и заставить кассы работать одновременно.
Рассмотрим стандартную ситуацию: у нас есть несколько ККМ, подключенных к одному рабочему месту. При попытке вызвать методы печати в цикле, 1С ожидает завершения каждой операции. Попытки использовать методы Оповестить() или ВыполнитьОбработчикОповещения() не приносят результата, так как они лишь передают управление внутри того же самого основного потока интерфейса. Пока драйвер занят передачей данных в порт ККТ, интерфейс «зависает», и следующий вызов ждет своей очереди.
Механизм фоновых заданий в 1С реализован на стороне сервера. В файловом варианте или при необходимости прямого доступа к локальным портам (COM/USB) через клиентское приложение, серверные задания не могут напрямую «дотянуться» до драйвера, установленного на конкретном ПК пользователя без сложных дополнительных прослоек.
Проанализируем наиболее стабильный промышленный подход — использование специализированного ПО, такого как KkmServer или аналогичных решений. Суть метода заключается в выносе логики управления оборудованием за пределы 1С.
Алгоритм работы выглядит следующим образом:
HTTPСоединение и отправляем JSON-пакет с данными чека на локальный адрес сервиса (например, http://localhost:5893).Пример формирования запроса в 1С:
Соединение = Новый HTTPСоединение("localhost", 5893);
Запрос = Новый HTTPЗапрос("/Execute/PrintCheque");
Запрос.УстановитьТелоИзСтроки(ДанныеЧекаВФорматеJSON);
// Отправляем и не ждем физического окончания печати ленты
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если вы используете современное оборудование АТОЛ и драйверы 10-й версии, разберем встроенную возможность — Web-сервер АТОЛ. Производитель уже заложил механизм управления очередью печати через HTTP/JSON.
Выясним причину, почему это эффективно: при такой архитектуре 1С общается не с COM-объектом драйвера, который блокирует поток, а с сетевым интерфейсом. Это позволяет отправлять команды на разные кассы (идентифицируемые по ID или серийному номеру) практически одновременно. Драйвер сам распределяет потоки данных по портам.
Если готовые платные решения не подходят, рассмотрим вариант реализации собственного «сервиса-прокладки», как это сделал автор обсуждаемой темы. Этот способ отлично подходит для 1С программистов, владеющих дополнительными языками программирования (C++, C#, Python).
Логика системы строится на отложенной обработке:
Рассмотрим пример кода 1С для такой выгрузки:
Процедура ОтправитьНаПечатьПараллельно(ДанныеЧека)
ИмяФайла = "C:\PrintQueue\" + Строка(Новый УникальныйИдентификатор) + ".json";
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.ОткрытьФайл(ИмяФайла);
ЗаписатьJSON(ЗаписьJSON, ДанныеЧека);
ЗаписьJSON.Закрыть();
// 1С свободна, сервис подхватит файл и напечатает его в фоне
КонецПроцедуры
Посмотрим на возможности современных версий платформы. Использование директивы &Асинхрон и оператора Ждать позволяет реализовать неблокирующий интерфейс. Хотя это не является честной многопоточностью (код всё равно выполняется поочередно в одном потоке приложения), использование асинхронных методов работы с внешними компонентами позволяет кассиру продолжать работу с формой, пока драйвер обрабатывает команду в фоновом режиме платформы.
При разработке параллельной печати следует учитывать несколько критических моментов:
ПодключитьОбработчикОжидания).Проанализировав ситуацию, можно сделать вывод: наиболее надежным и масштабируемым способом является переход на HTTP-взаимодействие с кассовым оборудованием, так как это штатно позволяет реализовать асинхронность и параллелизм, недоступные при прямом использовании старых COM-компонент в рамках одного сеанса 1С.