Почему при загрузке данных из Розницы в УТ возникают ошибки «Процедура не определена» и зависают сеансы?

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

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


{ОбщийМодуль.INT_Сервисный.Модуль(418,10)}: Процедура или функция с указанным именем не определена (ПолучитьСерверТО)
    Если Не ПолучитьСерверТО().ОтключитьОбработкиОбслуживания() Тогда

{ОбщийМодуль.INT_Сервисный.Модуль(569,5)}: Процедура или функция с указанным именем не определена (Предупреждение)
    Предупреждение("Выбранный файл не является внешней обработкой.");

Разберем эту ситуацию по шагам. На первый взгляд кажется нелогичным, что обмен данными, который должен работать в фоне, затрагивает участки кода, связанные с торговым оборудованием или выводом интерактивных сообщений на экран. Более того, пользователи могут начать жаловаться на зависание программы — сессии 5-10 человек могут просто остановиться. Проанализируем, почему так происходит и как грамотно устранить эту проблему.

Разберем суть проблемы: контекст выполнения кода

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

Посмотрим на эти функции внимательнее:

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

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

Проанализируем причину зависания сеансов пользователей

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

Если код написан таким образом, что вызов метода Предупреждение (или подобных ему, например, Вопрос) все-таки начинает выполняться на сервере или в COM-соединении, процесс «повисает». Программа открывает невидимое диалоговое окно в памяти сервера и бесконечно ждет, пока кто-нибудь нажмет в нем кнопку. Так как физически этого никто сделать не может, фоновое задание обмена блокируется на неопределенный срок.

При этом, процесс обмена данными работает внутри транзакции. Он удерживает блокировки на таблицах базы данных (на справочниках, документах, регистрах), в которые пытался записать данные. Сеансы обычных пользователей, которые в этот момент пытаются открыть, провести или сохранить те же самые объекты, натыкаются на эти транзакционные блокировки и закономерно зависают, ожидая ответа от сервера.

Почему проблема появилась «внезапно», если код не меняли?

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

Как правильно решить проблему: подробная инструкция

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

Шаг 1. Диагностика модулей в Конфигураторе

Для начала нам нужно найти все подобные ошибки. Не стоит ждать очередного падения обмена. Выполним проверку вручную:

  1. Откройте Конфигуратор базы, в которой возникает ошибка (база-приемник).
  2. Перейдите в меню Сервис -> Параметры, выберите вкладку Модули -> Проверка.
  3. Установите галочку напротив пункта Сервер и Внешнее соединение.
  4. В главном меню выберите Конфигурация -> Проверка модулей.

Система выдаст вам полный список мест, где клиентские функции вызываются в серверном контексте. Именно здесь и кроется проблема.

Шаг 2. Использование директив препроцессора

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

Рассмотрим пример того, как нужно оборачивать клиентский код инструкциями препроцессора, чтобы сервер игнорировал его при компиляции:


Процедура КнопкаНажатиеОбработкаТерминалРозничной() Экспорт
    
    // Оборачиваем клиентский код в директиву
    #Если Клиент Тогда
        Если Не ПолучитьСерверТО().ОтключитьОбработкиОбслуживания() Тогда
            Возврат;
        КонецЕсли;
        
        // Интерактивные сообщения тоже должны быть только на клиенте
        Предупреждение("Операция выполнена");
    #КонецЕсли

    // Далее идет код, который может выполняться на сервере...

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

Использование директивы #Если Клиент Тогда ... #КонецЕсли (или #Если Не ВнешнееСоединение И Не Сервер Тогда) укажет платформе, что данный фрагмент кода нужно компилировать только на рабочих местах пользователей.

Шаг 3. Разделение общих модулей

Хорошим тоном в разработке на платформе 1С является разделение общих модулей по контексту их выполнения. Проанализируем свойства проблемного модуля. Если в модуле установлены одновременно флажки «Клиент (управляемое приложение)», «Сервер» и «Внешнее соединение», риск возникновения таких ошибок возрастает в разы.

Рекомендуется вынести все процедуры работы с оборудованием и интерфейсом в отдельный модуль, например INT_СервисныйКлиент, и оставить галочку только на клиенте. Серверные процедуры оставить в INT_СервисныйВызовСервера. Это исключит проблему на корню.

Шаг 4. Очистка кэша и снятие зависших процессов

Если вы исправили код, но сеансы продолжают висеть, значит, старые фоновые задания все еще активны в памяти сервера 1С. Выполним следующие действия:

  1. Откройте Консоль администрирования кластера серверов 1С.
  2. Найдите сеансы пользователя, под которым выполняется обмен данными (часто это служебный пользователь «Обмен» или «Администратор»).
  3. Вручную удалите (разорвите) зависшие сеансы и фоновые задания обмена.
  4. Для надежности рекомендуется остановить службу сервера 1С, очистить папку сеансовых данных (кэш сервера) и запустить службу заново.

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

← На главную