Как прервать выполнение функции получения веса в 1С по таймауту

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

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

В данной статье мы разберем, как автоматизировать прерывание функции по истечении заданного времени (например, 3 секунды), чтобы программа продолжала работу даже при отсутствии ответа от оборудования.

Анализ причин проблемы

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

Рассмотрим основные способы решения этой задачи, начиная от самых современных методов платформы 1С:Предприятие 8.3 и заканчивая аппаратными настройками.

Решение №1. Использование фоновых заданий с методом ОжидатьЗавершенияВыполнения

Это наиболее эффективный и правильный метод для современных конфигураций на управляемых формах. Мы выносим процедуру опроса весов в отдельный поток (фоновое задание), а в основном потоке просто ждем ответа в течение определенного времени.

Разберем по шагам, как модифицировать ваш код:

  1. Вынесем логику опроса весов в экспортную процедуру серверного модуля (или модуля менеджера).
  2. Запустим фоновое задание из клиентского кода.
  3. Используем метод ФоновыеЗадания.ОжидатьЗавершенияВыполнения() для ограничения времени.

Посмотрим на пример реализации:


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

КонецПроцедуры

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

Решение №2. Фоновое задание + Обработчик ожидания (для асинхронного интерфейса)

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

  1. При нажатии кнопки «Вес» запускаем фоновое задание.
  2. Включаем ПодключитьОбработчикОжидания("ПроверитьСтатусФоновогоЗадания", 1).
  3. В переменной формы запоминаем время старта.
  4. В процедуре ПроверитьСтатусФоновогоЗадания проверяем состояние задания.
  5. Если прошло более 3 секунд и результата нет — отключаем обработчик и принудительно завершаем задание.

Проанализируем преимущества: кассир видит прогресс (например, крутящийся индикатор), но программа не «замерзает», так как управление возвращается в очередь событий Windows каждую секунду.

Решение №3. Программная настройка таймаута в драйвере оборудования

Иногда проблему можно решить гораздо проще, не прибегая к многопоточности. Большинство внешних компонент (DLL) для весов имеют встроенные свойства таймаута. Выясним причину, по которой ваша функция ПолучитьВесСЭлектронныхВесов ждет вечно. Скорее всего, при инициализации объекта драйвера параметр Timeout установлен в значение 0 (бесконечность) или слишком большое число (30 секунд).

Рассмотрим пример настройки объекта драйвера:


// Пример настройки драйвера АТОЛ/Штрих-М
ОбъектДрайвера.Timeout = 2000; // Устанавливаем 2 секунды
Результат = ОбъектДрайвера.ПолучитьВес();

Если Результат < 0 Тогда
    // Драйвер сам вернет ошибку по таймауту через 2 секунды
    // 1С не зависнет, а просто перейдет в блок обработки ошибки
    Сообщить(ОбъектДрайвера.ОписаниеОшибки);
КонецЕсли;

Важный совет: Проверьте настройки оборудования в самой 1С (Администрирование -> Подключаемое оборудование). Часто там есть поле «Таймаут», которое передается в драйвер при подключении.

Аппаратные рекомендации и работа с COM-портами

Если вы используете переходники USB-to-COM, проблема «зависания» часто кроется в драйвере самого адаптера или настройках энергосбережения Windows. Проанализируем дополнительные шаги по стабилизации связи:

Резюме

Для надежной работы РМК рекомендуется комбинированный подход: Во-первых, настройте минимально возможные таймауты (1-2 сек) непосредственно в параметрах подключения оборудования в 1С. Во-вторых, если драйвер игнорирует настройки и продолжает вешать поток, внедрите механизм фонового задания с принудительной отменой через ОжидатьЗавершенияВыполнения или Задание.Отменить(). Это гарантирует, что работа кассира не будет прервана необходимостью перезагрузки компьютера.

← На главную