В статье рассказывается как можно сделать аналогичный объект средствами 1С v7.7
Существует ряд задач, которые требуют строго последовательного исполнения. Чаще всего это возникает при многопоточном программировании, в этом случае используются критические секции, но иногда надо синхронизировать и разные приложения — для этого в существуют такие объекты ядра операционной системы как Мьютекс-ы.
В википедии есть подробная статья про них, если кому интересно: http://ru.wikipedia.org/wiki/Мьютекс
Для чего это может понадобится в 1С ?
Например вы хотите, что бы при входе в систему любого пользователя выполнялось какое-либо действие (загрузка/выгрузка файла обмена, загрузка валют, запуск построения статистики при первом входе за день и т.д.) или вам просто очень бы не хотелось, что бы два пользователя одновременно запустили одну и ту же обработку (например обмен с сайтом), т.к. результат одновременной обработки из двух мест непредсказуем.
Отсюда вытекает задача объекта синхронизации, владеть которым в момент времени мог бы только один сеанс. Я предлагаю для этого обходится стандартными возможностями 7.7
Полное описание к задаче:
- Должен быть объект который монопольно можно захватить из 1С.
- Обращаться к объекту должно быть можно их разных запущенных сеансов, разных компьютеров, в идеале разных ИБ
- При аварийном завершении сеанса захватившего объект — захват должен сниматься, что бы не оказалось подвисших блокировок.
Из описания стало понятно, что это должен быть файл на который получен эксклюзивный доступ — в этом случае его никто другой не сможет открыть даже для чтения. Это удобно тем, что при падении 1С — винда сама отследит, что владельца файла больше нет и снимет с файла блокировку.
Таким свойством обладает открытый через XBase файл dbf. На этом и построен алгоритм.
Всего работа с синхронизацией состоит в данном случае из 2х функций: Lock() и UnLock(): первая пытается захватить объект и если это получается — возвращает (1), если не получается по каким — либо причинам — возвращает (0) и тут уже делайте, что хотите: завершайте работу или в цикле пробуйте получить объект себе во владение, как угодно. Снятие блокировки происходит при вызове UnLock() или при завершении обработки (разрушении объекта XBase).
//Ж*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖSЖЖPЖЖ*ЖЖ*Ж
Перем ФайлСинхронизации, ИмяФайлаСинхронизации;
//Ж*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖSЖЖPЖЖ*ЖЖ*Ж
Функция Lock()
Если ПустоеЗначение(ФайлСинхронизации) = 0 Тогда
//Трас(«Объект блокировки уже создан»);
Возврат 1;
КонецЕсли;
Попытка
ФайлСинхронизации = СоздатьОбъект(«XBase»);
ФайлСинхронизации.КодоваяСтраница(1);
ФайлСинхронизации.ДобавитьПоле(«Name»,«S», 64, 0);
ФайлСинхронизации.СоздатьФайл(ИмяФайлаСинхронизации);
ФайлСинхронизации.Добавить();
ФайлСинхронизации.Name = ИмяПользователя();
ФайлСинхронизации.Записать();
ФайлСинхронизации.ЗакрытьФайл();
Если ФС.СуществуетФайл(ИмяФайлаСинхронизации) = 1 Тогда
ФайлСинхронизации.ОткрытьФайл(ИмяФайлаСинхронизации);
Если ФайлСинхронизации.Первая() = 1 Тогда
Если НРег(СокрЛП(ФайлСинхронизации.Name)) = НРег(СокрЛП(ИмяПользователя())) Тогда
Возврат 1;
Иначе
//Трас(«Не удалось получить блокировку, файл перехватил: » + ФайлСинхронизации.Name, «!»);
КонецЕсли;
Иначе
//Трас(«Не удалось спозиционироваться в файле блокировки», «!»);
КонецЕсли;
ФайлСинхронизации.ЗакрытьФайл();
Иначе
//Трас(«Не удалось создать файл блокировки», «!»);
КонецЕсли;
Исключение
//Трас(«Исключение при блокировке: » + ОписаниеОшибки(), «!»);
КонецПопытки;
//Трас(«Очищен объект блокировки (после неудачной попытки захвата)»);
ФайлСинхронизации = ПолучитьПустоеЗначение();
Возврат 0;
КонецФункции
//Ж*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖ*ЖЖSЖЖPЖЖ*ЖЖ*Ж
Процедура UnLock()
Если ПустоеЗначение(ФайлСинхронизации) = 1 Тогда
//Трас(«Объект блокировки не был создан»);
КонецЕсли;
Попытка
ФайлСинхронизации.ЗакрытьФайл();
Исключение
//Трас(«Исключение при снятии блокировки: » + ОписаниеОшибки(), «!»);
КонецПопытки;
//Трас(«Очищен объект блокировки»);
ФайлСинхронизации = ПолучитьПустоеЗначение();
КонецПроцедуры
Перед первым вызовом началом работы надо задать полное имя для файла, который будет объектом синхронизации в ИмяФайлаСинхронизации.
Удачного кодинга!