Продолжение цикла статей о многопоточных вычислениях в 1С
Статья продолжает данную статью.
...Но теперь, когда на многоядерных процессорах начали работать обычные приложения, параллельное программирование быстро становится технологией, которую должен освоить и уметь применять любой профессиональный разработчик ПО.
Intel software...
Как это все работает?
Итак, многопоточность в клиент-серверной архитектуре 1С работает через запуск фоновых заданий с данными для обработки. Если вы хотите обработать множество данных (например, исправить проводки в куче документов или заполнить какой-нибудь реквизит документа, справочника, ...), которые не требуют соблюдения определенной последовательности, то многопоточность может значительно ускорить выполнение.
Но существуют задачи, которые, выполняясь в несколько потоков, требуют, чтобы определенные операции никогда не выполнялись одновременно несколькими потоками. Примером тому может служить, например, инициализация нативной внешней компоненты печати штрих-кодов на сервере 1С. 1С 8.3.5.хххх при одновременном выполнении кода подключения данной компоненты отваливается rphost, на котором выполняется задание. 1С 8.2.19.102 (если мне не изменяет память) rphost не рубит, но штрих-код при этом не генерируется - выходит пустой квадратик.
Для того, чтобы "заблокировать" определенный участок кода для монопольного выполнения, в правильных языках программирования, поддерживающих мультипоточность, и существуют мьютексы. В принципе, мьютекс - это некоторый объект, который блокируется первым процессом, пожелавшим этого. Остальные процессы валятся в "exception", т.е. в исключение.
Реализация мьютекса в 1С
Реализовать мьютекс можно разными способами. Например, обычной блокировкой. Но что блокировать при создании внешней компоненты? В программах часто для блокировки используется файл. Я использую объект ЗаписьТекста - таким образом можно создавать именованные блокировки, не тратя ресурсов системы и не блокируя ничего на сервере приложений 1С - он и так периодически на блокировках подглючивает.
Реализуем функцию установки блокировки и подумаем о том, как ее снять.
Давайте создадим функцию, создающую именованную блокировку и возвращающую результат. Для этого определим, какие действия должна совершить программа.
Математическая модель установки именованной блокировки:
1. Создадим объект ЗаписьТекста с именем файла во временном каталоге.
2. Если удалось создать - возвращаем истину, если не удалось - ложь.
3. В параметре функции таже будем возвращать объект "ЗаписьТекста", чтобы было что разблокировать.
Функция СоздатьБлокировку(ИмяБлокировки, файлБлокировки)
Попытка
файлБлокировки = Новый ЗаписьТекста(КаталогВременныхФайлов() + ИмяБлокировки);
Возврат Истина;
Исключение
Возврат Ложь
КонецПопытки;
КонецФункции
Тут мы создаем запись текста с именем файла блокировки. Если блокировка уже установлена - файл открыт на запись - мы попадем в исключение и возвращаем "ЛОЖЬ". Таким образом можно оградить определенный код от одновременного выполнения.
Функция ПодключитьВнешнююКомпонентуПечатиШтрихкода() Экспорт
файлБлокировки = Неопределено;
Пока НЕ СоздатьБлокировку("ПечатьШтрихКода", файлБлокировки) Цикл
// пустой цикл
КонецЦикла;
ПодключениеВыполнено = ПодключитьВнешнююКомпоненту("ОбщийМакет.КомпонентаПечатиШтрихкодов", "КартинкаШтрихкода", ТипВнешнейКомпоненты.Native);
// убираем блокировку
файлБлокировки.Закрыть();
...
...
КонецФункции
Заключение
Данный пример блокировки может помочь в реализации самого широкого спектра задач, в которых можно использовать многопоточность и для которых нужны фрагменты кода, выполняющегося монопольно.