Удержание СОМ-соединения между вызовами сервера

01.06.21

Разработка - Универсальные функции

Избежать повторной установки серверного СОМ-соединения, вызывая его откуда угодно и как угодно.

Уже много лет COM-технология "отмирает", да всё никак не отомрёт. Несмотря на всякие там кроссплатформенности и модные способы обмена.

Не буду в сотый раз рассказывать, что такое COM-соединение, ибо материалов предостаточно, и уж тем более не буду углубляться в технические подробности, кто там кому вне/внутри-процессный, чем соединитель от оле-сервера отличается, что такое маршалинг и как лицензии захватываются. Я сейчас не об этом.

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

Идея простейшая: на каждое СОМ-соединение запускаем фоновое задание, в методе которого создаётся собственно соединение, а дальше идёт бесконечный цикл. В этом цикле мы ждём команды от вызывающего сеанса - я их передаю через константу, но при желании можно извратиться как угодно, хоть регистр замутить - обрабатываем эти команды, т.к. весь контекст COMObject'а у нас в рамках процедуры есть. Результаты отдаём вызывающему - я сделал через сообщения пользователю, но опять же, можно всяко. Когда соединение становится ненужным, даём команду, и фоновое задание прекращается изнутри (либо отменяем его извне, как его авторы). Также смотрим из фонового, если вызывающий сеанс закончился, то и из бесконечного цикла выходим и фоновое завершаем. Хотя, конечно, лучше завершать в явном виде, т.к. в режиме отладки, ещё и в файловой версии, такой сеанс может и заклинить, в т.ч. с утечкой памяти.

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

Итак.

 
 Весь нужный код

 

Плюсы:
* Существенно убыстряет работу и отладку (если поставить долгий таймаут опроса прекращения сеанса, или внешками при работающем сеансе). 
* Позволяет обратиться к СОМ-объекту откуда угодно, из любого контекста, любой формы и модуля (фоновое-то по ключу есть и крутится, если, конечно, сам СОМ вдруг не умер).

Минусы:
* Соединение создаётся не в памяти "сеанса-клиента", а в памяти служебного хост-процесса, держащего фоновое; это может быть чуть дольше в момент установки соединения.
* Если действия длительные, важно подобрать таймауты, чтобы взаимодействие вызвавшего сеанса и фонового задания успевало корректно отработать в обе стороны.
* Извращаться с передачей туда-сюда несколько неудобно.

 

Да, всё это применимо только для Windows. Да, на файловых базах можно так работать лишь с одним соединением. И, подозреваю, что я изобрёл велосипед. Но - столько простейших и очевидных вещей выкладывается, что почему бы и нет?

Кому есть кинуть тухлый помидор, давайте; может, я упустил что-то очевидное.

Кому пригодится - вот и хорошо.

COM соединение OLE COMConnector

См. также

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

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

21.05.2024    20244    dimanich70    81    

145

Универсальные функции Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

Задача: вставить картинку из буфера обмена на форму средствами платформы 1С.

1 стартмани

18.03.2024    4100    3    John_d    11    

57

Универсальные функции Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Пришлось помучиться с GUID-ами немного, решил поделиться опытом, мало ли кому пригодится.

12.02.2024    18209    atdonya    24    

57

Универсальные функции Программист Платформа 1С v8.3 Бесплатно (free)

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

30.11.2023    5511    ke.92@mail.ru    16    

65

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    14778    YA_418728146    7    

166

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    3594    57    progmaster    8    

4

Инструментарий разработчика Универсальные функции Платформа 1С v8.3 Конфигурации 1cv8 1С:Розница 2 1С:ERP Управление предприятием 2 1С:Бухгалтерия 3.0 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Зарплата и Управление Персоналом 3.x Абонемент ($m)

Копирует в буфер значения из списков, из ячеек отчетов, таблиц, настроек списков, других отборов и вставляет в выбранную настройку отбора. Работает с Объект не найден. Работает как в одной так и между разными базами 1С. Использует комбинации [Alt+C] Копировать список, [Alt+V] Вставить список. Также для копирования данных используется стандартная [Ctrl+C] (например из открытого xls, mxl, doc и т.п. файла скопировать список наименований)

1 стартмани

13.10.2022    18500    171    sapervodichka    112    

135
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. SlavaKron 01.06.21 19:03 Сейчас в теме
Учитывая, что в 1С нет аналога sleep(), не будет ли бесконечный цикл грузить процессор? И хотелось бы уточнить, почему временное хранилище, параметр сеанса и модуль с повторным использованием не работают (хотя бы с какой версии платформы)? Имеются решения, которые кешируют соединение во временном хранилище и работают по сей день, поэтому возник такой вопрос.
2. Yashazz 4791 01.06.21 19:45 Сейчас в теме
(1) Будет некоторым образом, конечно, но это пренебрежимо малая нагрузка. С какой версии не работают, не знаю, но на 8.3.18.1483 не взлетело, а если даже и взлетит - никакой гарантии, что в следующем релизе это поведение не изменится. А временное хранилище нехорошо уже хотя бы из-за его 20 минут хранения и сбрасывающих вызовов.
3. Malfarion 261 01.06.21 21:14 Сейчас в теме
"функцией модуля повторного использования" обрабатывается корректно, используем в боевом проекте, единственный небольшой минус что из-за особенностей повторного использования если не обращаться в течении 6 минут либо через 20 минут в любом случае кэш повторного использования очищается.
4. Yashazz 4791 01.06.21 21:29 Сейчас в теме
(3) у вас какой релиз? У меня при каждом обращении заново соединение устанавливалось. При любых интервалах времени, хоть 3 раза в минуту.
5. Malfarion 261 01.06.21 21:54 Сейчас в теме
6. Malfarion 261 01.06.21 22:07 Сейчас в теме
Так-же делюсь адекватным кодом для паузы

// Останавливает выполнение кода на заданное время.
//
// Параметры:
//  Секунд - Число - время ожидания в секундах.
//
Процедура Пауза(Секунд) Экспорт
	
	ТекущийСеансИнформационнойБазы = ПолучитьТекущийСеансИнформационнойБазы();
	ФоновоеЗадание = ТекущийСеансИнформационнойБазы.ПолучитьФоновоеЗадание();
	
	Если ФоновоеЗадание = Неопределено Тогда
		Параметры = Новый Массив;
		Параметры.Добавить(Секунд);
		ФоновоеЗадание = ФоновыеЗадания.Выполнить("РУ_ОбщегоНазначения.Пауза", Параметры);
	КонецЕсли;
	
	ФоновоеЗадание.ОжидатьЗавершенияВыполнения(Секунд);
	
КонецПроцедуры
Показать



"РУ_ОбщегоНазначения.Пауза" - это сам этот метод, т.е он вызывает сам себя и ждет таймаута.
kot26rus; +1 Ответить
7. Yashazz 4791 01.06.21 23:07 Сейчас в теме
(6) Знаю такой способ, да, в любом случае спасибо. Просто мне не очень хотелось мутить два фоновых. А так - и wsh можно, и ещё всяко...

8.3.10.2580 Файловая
Чёрт её знает, всё может быть... Не берусь категорично утверждать.
8. Malfarion 261 02.06.21 00:11 Сейчас в теме
(7) wsh и еще всякое платформозависимое. А в 2х ФЗ ничего страшного нет
9. Yashazz 4791 02.06.21 06:38 Сейчас в теме
(8) Так и сам СОМ, кхм, платформозависимый)
10. Yashazz 4791 02.06.21 08:05 Сейчас в теме
(8)
в 2х ФЗ ничего страшного нет
Не считая того, что в файловой оно не взлетит.
11. Malfarion 261 02.06.21 13:33 Сейчас в теме
(10) С чего это вдруг не взлетит?)
15. Yashazz 4791 03.06.21 16:39 Сейчас в теме
(11) Кхм. Документацию читать не пробовали?
16. Malfarion 261 03.06.21 17:45 Сейчас в теме
(15) Сразу видно что вы код даже не запускали. При выполнении его внутри фонового задания он не будет создавать новое фоновое задание и он работает хорошо с любой СУБД в том числе с файловой. За это отвечает вот эта функция ТекущийСеансИнформационнойБазы.ПолучитьФоновоеЗадание().
Но я смотрю что вам помощь не нужна, раз вы меня документацию отправляете читать, не очень вежливо. Пожалуй моё присутствие тут больше не требуется, пойду читать документацию по вашему совету.
17. Yashazz 4791 04.06.21 07:52 Сейчас в теме
(16) Мне-то пауза нужна в основном не внутри фонового задания, а вне его - когда вызывающий процесс ждёт запуска ком-соединения. А извне - это второе фоновое, которое известно как себя ведёт в файловом варианте.
18. Malfarion 261 04.06.21 12:12 Сейчас в теме
(17) Товарищь, я еще раз вам повторяю, данный код паузы работает, внутри , снаружи, сбоку, сзади, в полнолуние, в дождь, в файловой, в клиент - серверной, на любом клиенте, когда уже запущено другое фоновое задание, когда оно не запущено.
Вы не до конца понимаете особенность работы фоновых заданий в файловом варианте, занимаетесь какой-то демагогией вместо того чтобы попробовать готовые код.
19. Yashazz 4791 14.06.21 17:40 Сейчас в теме
(18) Ну попробовал. Не взлетело, как и следовало ожидать. Для интереса сделал отладку через ЖР - первое стартует и второму уже стартовать не даёт. Упс) ...и чего бы это вдруг, правда?)
20. Malfarion 261 14.06.21 21:40 Сейчас в теме
(19) Я реально не понимаю, вы вроде опытный парень, рейтинг высокий, статьи пишите, но не можете в простом коде разобраться в течении недели. Зачем тут фактический запуск второго фонового задания, которое вам так не дает покоя? Не понимаю что вы там попробовали, приведите "кейс" где это этот метод не заработает. Тут вообще не играет никакой роли запустилось ли второе ФЗ или нет, "паузу" реализует метод ОжидатьЗавершенияВыполнения который выполняется в том потоке где вы вызвали "паузу", и ему вообще не важно запустилось ли другое ФЗ, не запустилось, стоит ли оно "в очереди" или еще что-то, оно прождет указанное количество секунд и пойдет выполнять код дальше.
Единственный плохой "эффект" в той реализации которую я скинул может быть - что в файловом варианте, если "служебное" (второе как вы его называете) фоновое задание встанет "в очередь", платформа его выполнит позже, когда до него дойдет очередь, и потенциально другие "полезные" ФЗ из-за этого выполнятся позже. Но это должно решаться примерно вот так :

// Останавливает выполнение кода на заданное время.
//
// Параметры:
//  Секунд - Число - время ожидания в секундах.
//
Процедура Пауза(Секунд) Экспорт
	
	ТекущийСеансИнформационнойБазы = ПолучитьТекущийСеансИнформационнойБазы();
	ФоновоеЗадание = ТекущийСеансИнформационнойБазы.ПолучитьФоновоеЗадание();
	
	Если ФоновоеЗадание = Неопределено Тогда
		Параметры = Новый Массив;
		Параметры.Добавить(Секунд);
		ФоновоеЗадание = ФоновыеЗадания.Выполнить("Э_ОбщегоНазначения.Пауза", Параметры);
	КонецЕсли;
	
	ФоновоеЗадание.ОжидатьЗавершенияВыполнения(Секунд);
	
	//Смотри тут <
	Если Параметры<>Неопределено Тогда
		ФоновоеЗадание.Отменить();
	КонецЕсли;	
	
КонецПроцедуры
Показать
21. Yashazz 4791 14.06.21 21:51 Сейчас в теме
(20) Вооот. На том 8.3.6.2237, на котором я это делаю, всё в очередь-то и ставится!

Я в коде не разбирался, у меня других дел полно; сегодня только пару минут выкроил)
12. Yashazz 4791 03.06.21 09:07 Сейчас в теме
Забавно. Вот была https://infostart.ru/1c/articles/331683/ с кучей плюсов, хотя там а) совсем примитив, б) могло сломаться и однажды таки сломалось. А вот моё решение, стабильное и, скажем так, методически корректное. Но плюсов не наблюдается. Прикольно, да)
ZhokhovM; +1 Ответить
13. bulpi 217 03.06.21 11:53 Сейчас в теме
(12)
Потому что оно простое и не стремное. Фоновое задание с бесконечным циклом - это стремно, я так не буду делать никогда. При всем уважении.
14. Yashazz 4791 03.06.21 12:42 Сейчас в теме
(13) Ага, только оно не работает и работать перестало после какого-то обновления внезапно) Потому что базировалось на нечётко формализованной возможности платформы. А представьте, каково тем, кто на этом предположении серьёзный бизнес-процесс построил) И что, ненадёжное и неработоспособное - это "не стрёмное"?))
Оставьте свое сообщение