Особенности компиляции общих клиент-серверных модулей в управляемом приложении 1С 8.2

Особенности компиляции общих клиент-серверных модулей в управляемом приложении 1С 8.2

В данной статье я буду употреблять выражение «клиентский(серверный) экземпляр модуля». «Клиентский экземпляр модуля» — это совокупность процедур и функций данного общего модуля, которые будут скомпилированы на стороне клиента. Аналогично: «Серверный экземпляр модуля» это совокупность процедур и функций данного общего модуля, которые будут скомпилированы на стороне сервера. В принципе это понятие означает тоже, что и «клиентский(серверный) контекст», но на мой взгляд, применительно к общим модулям более точно отражает суть.
Рассмотрим общий модуль, у которого установлены флажки «Клиент (управляемое приложение)» и «Сервер», разрешим вызов сервера с клиента, установив флажок «Вызов сервера». Основной момент, на который следует обратить внимание, это то, что в данном случае будет скомпилировано ДВА ЭКЗЕМПЛЯРА этого общего модуля, один на сервере, один на клиенте. Все процедуры и функции, объявленные с директивой компиляции &НаСервере, попадут в серверный экземпляр модуля, соответственно все процедуры и функции, объявленные с директивой компиляции &НаКлиенте, попадут в клиентский экземпляр модуля. Все процедуры и функции, объявленные без директив компиляции попадут и в клиентский, и в серверный экземпляры модуля.
Рассмотри пример, допустим, в тексте общего клиент-серверного модуля, который называется «МодульКлиентСервер» определены следующие процедуры:

// Попадет в серверный экземпляр модуля
&НаСервере
Процедура ПроцедураОбщегоМодуля() Экспорт
	Сообщить("Сервер");
КонецПроцедуры

// Попадет в клиентский экземпляр модуля
&НаКлиенте
Процедура ПроцедураОбщегоМодуля() Экспорт
	Сообщить("Клиент");
КонецПроцедуры

Заметьте, несмотря на то, что процедуры называются одинаково, никакой синтаксической ошибки не возникает, так как они будут скомпилированы в разных экземплярах модуля. Если у модуля установлен флажок «Вызов сервера», а у нашего модуля он установлен, то возникает вполне закономерный вопрос: Какая из двух одноименных процедур будет вызвана? Из серверного или клиентского экземпляра модуля? Тут действует так называемое правило «ближнего вызова»: если вызов осуществляется с клиента – будет вызвана процедура из клиентского экземпляра модуля, если с сервера – то серверного. Вызов процедур общего модуля из модуля любой формы:

&НаКлиенте
Процедура Команда1(Команда)
	МодульКлиентСервер.ПроцедураОбщегоМодуля();// <-КЛИЕНТСКИЙ экземпляр
	ВызовСервера();	
КонецПроцедуры

&НаСервере
Процедура ВызовСервера()
	МодульКлиентСервер.ПроцедураОбщегоМодуля();// <-СЕРВЕРНЫЙ экземпляр
КонецПроцедуры

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

// Попадет в оба экземпляра модуля
Процедура ПроцедураОбщегоМодуля() Экспорт
	#Если НаСервере Тогда
	    Сообщить("Сервер");
	#КонецЕсли
	#Если НаКлиенте Тогда
	    Сообщить("Клиент");
	#КонецЕсли
КонецПроцедуры

Как было написано выше, в этом случае ПроцедураОбщегоМодуля() будет скомпилирована в обоих экземплярах модуля, но код в клиентском и серверном экземплярах будет РАЗНЫЙ.

// В серверный экземпляр модуля попадет:
Процедура ПроцедураОбщегоМодуля() Экспорт
	Сообщить("Сервер");
КонецПроцедуры

// В клиентский экземпляр модуля попадет:
Процедура ПроцедураОбщегоМодуля() Экспорт
	Сообщить("Клиент");
КонецПроцедуры

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

Если публикация помогла Вам справится с проблемой, решить задачу или расширить свои знания - поддержите автора.

Комментарии:

  1. ysavinov:

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

    1. Администратор:

      Из серверной процедуры нельзя вызвать клиентскую.

  2. k1us181b:

    =несмотря на то, что процедуры называются одинаково, никакой синтаксической ошибки не возникает, так как они будут скомпилированы в разных экземплярах модуля=
    возникает.
    {ОбщийМодуль.МодульКлиентСервер.Модуль(9,11)}: Процедура или функция с указанным именем уже определена (ПроцедураОбщегоМодуля)
    Процедура <>ПроцедураОбщегоМодуля() Экспорт

    1. admin:

      Дочитайте статью до конца.

  3. Максим:

    Отлично все рассказал.
    Я для себя все расставил по местам. Получил так сказать понимание предмета
    Спасибо.

  4. Александр:

    а можно ли в обычном приложении заставить выполняться некий код на сервере?
    я так понял для толстого клиента директивы сервер/клиент игнорируются и весь модуль компилируется на компе клиента, соответственно на компе клиента и исполняется, а как-то вызывать в тостом клиенте и обычном приложении (на обычных формах) процедуры, которые будут исполняться на сервере, можно?

    1. Администратор:

      Можно, для выполнения кода на сервере в обычном приложении используют общие модули с включенными флажками «Сервер» и «Вызов сервера»
      Процедуры и функции, которые содержаться в таких модулях выполняются на сервере

  5. Дмитрий:

    Спасибо.

Оставить комментарий на k1us181b