Имя: Пароль:
1C
1С v8
Заблокировать выполнение процедуры на сервере одновременно двумя пользователями
, ,
0 D_Sergeevich
 
09.07.13
13:22
День добрый.
Есть обработка которая получает файл через веб сервис, метод получения вызывается в процедуре на сервере.
Как заблокировать эту процедуру на время ее выполнения. т.е. чтобы пользователь не мог ее вызвать когда она отрабатывает для другого пользователя.

&НаКлиенте
Процедура Сформировать(Команда)
   data_start = Строка(Формат(Объект.НачалоПериода,"ДФ=dd.MM.yyyy"));
   data_end = Строка(Формат(Объект.КонецПериода,"ДФ=dd.MM.yyyy"));
   acc_source = Строка(Объект.Счет);
   name_source = "Данные - выписка";
   
   //Проверка заполнения полей
   Если data_start = '00010101' ИЛИ data_end = '00010101' ИЛИ  acc_source = "" Тогда
       Предупреждение("Пожалуйста заполните все поля!");
   Иначе
       ПодключениеКВебСервису(data_start, data_end, acc_source, name_source)    
       КонецЕсли;
КонецПроцедуры

//Подключени к веб сервису и вызов методов
&НаСервере
Процедура ПодключениеКВебСервису(data_start, data_end, acc_source, name_source)
   WSОпределение = Новый WSОпределения("C:/Service.wsdl");
   WSПрокси = Новый WSПрокси(WSОпределение,"http://tempuri.org/","Service1","Service1");
   WSПрокси.Пользователь = "*****";
   WSПрокси.Пароль = "*****";
   
   Данные = WSПрокси.GetDataWcf(name_source, acc_source, data_start, data_end);
   ДвоичныеДанные = WSПрокси.getFile(0);
   ДвоичныеДанные.Записать("C:\\test.xml");    
КонецПроцедуры
1 Поросенок Петр
 
09.07.13
13:25
А что случается если не "заблокировать" ?
2 D_Sergeevich
 
09.07.13
13:28
(1) Зависает соединение с веб сервисом. Получение файла идет около 30 сек. и на это время нужно блокировать выполнение другим пользователям.
3 Maxus43
 
09.07.13
13:29
ну взведи константу например, "Нелья". и проверяй... потом сбросишь
4 Поросенок Петр
 
09.07.13
13:31
Могу ошибаться, надо копать в сторону Таймаут.

Новый WSПрокси(<Определение>, <URIПространстваИменСервиса>, <ИмяСервиса>, <ИмяТочкиПодключения>, ***<Таймаут>***)
5 D_Sergeevich
 
09.07.13
13:36
(4) Новый WSПрокси(<Определение>, <URIПространстваИменСервиса>, <ИмяСервиса>, <ИмяТочкиПодключения>)  Тут нету таймаута.
(3)Ну вот я как раз так и думал, завел константу типа булево "Блокировка", но не соображу где ее устанавливать и где проверять
6 Fragster
 
гуру
09.07.13
13:37
установка исключительной блокировки на константу
7 Fragster
 
гуру
09.07.13
13:37
см, как сделана синхронизация в v8: Многопоточный тест производительности 1с
8 Maxus43
 
09.07.13
13:39
(5) тут
&НаСервере
Процедура ПодключениеКВебСервису(data_start, data_end, acc_source, name_source)

сначала проверять, если Истина то возврат, иначе устанавливай и выполняй дальше. в конце процедуры снимай
9 Maxus43
 
09.07.13
13:40
ну и предусмотреть что свалится с ошибкой может, а константу надо таки сбросить всё равно
10 D_Sergeevich
 
09.07.13
13:45
(9) ага, благодарю!
А как проверить свалилась она с ошибкой или нет, чтоб в случае чего сбросить константу
11 Maxus43
 
09.07.13
13:46
вобще для этого используют ПОПЫТКА ИСКЛЮЧЕНИЕ, я хз тока ошибку вебсервиса поймёт ли
12 Fragster
 
гуру
09.07.13
13:46
не надо менять значение константы, надо выставить на нее исключительную блокировку - тогда другой сеанс не сможет выставить на нее свою блокировку, пока первый не снимет свою. профит!
13 Maxus43
 
09.07.13
13:47
(12) ты там вот в (7) найдёш сходу "см, как сделана синхронизация" если первый раз туда попадёшь?)
14 Maxus43
 
09.07.13
13:48
(12) игра блокировками или значением - разница принципиальная какая кстати?
15 Fragster
 
гуру
09.07.13
13:51
(13) глобальный поиск "Синхронизация" :)

(14) при отвале не надо думать, что rphost упадет и константа останется не в том состоянии.
16 Очкарик
 
09.07.13
13:51
(0) Установи исключительную блокировку на Объект в момент работы процедуры
17 Maxus43
 
09.07.13
13:55
(15) согласен, понадёжней будет
18 vde69
 
09.07.13
13:59
заведи справочник, один элемент - это твоя процедура, далее запрос "для изменения"
19 Fragster
 
гуру
09.07.13
14:03
(18) кстати да, если режим управления блокировками - автоматический - то ДЛЯ ИЗМЕНЕНИЯ вместо БлокировкаДанных надо использовать...
20 D_Sergeevich
 
09.07.13
14:04
Всем спасибо буду пробовать. Окончательный результат выложу, думаю многим пригодится
(19) режим блокировки в конфе у меня управляемый
21 D_Sergeevich
 
09.07.13
14:59
Нашел тот кусок кода из сылки
22 D_Sergeevich
 
09.07.13
15:00
Но почему то оно не блокирует и второй пользователь тоже может ставить Заблокировать()
Блокировка = Новый БлокировкаДанных;
   ЭлементБлокировки = Блокировка.Добавить("Константа.Синхронизация");
   ЭлементБлокировки.Режим = РежимБлокировкиДанных.Разделяемый;
   Блокировка.Заблокировать();
23 Fragster
 
гуру
09.07.13
15:06
Исключительный
24 D_Sergeevich
 
09.07.13
15:13
(23) Блокировка = Новый БлокировкаДанных;
   ЭлементБлокировки = Блокировка.Добавить("Константа.Блокировка");
   ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
   Блокировка.Заблокировать();

Тоже самое (
25 D_Sergeevich
 
09.07.13
15:19
Правильно я делаю?
&НаСервере
Процедура ПодключениеКВебСервису(data_start, data_end, acc_source, name_source)
   Блокировка = Новый БлокировкаДанных;
   ЭлементБлокировки = Блокировка.Добавить("Константа.Блокировка");
   ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
   Блокировка.Заблокировать();
   
   WSОпределение = Новый WSОпределения("C:/Service.wsdl");
   WSПрокси = Новый WSПрокси(WSОпределение,"http://tempuri.org/","Service1","Service1");
   WSПрокси.Пользователь = "***";
   WSПрокси.Пароль = "***";
   
   Данные = WSПрокси.GetDataWcf(name_source, acc_source, data_start, data_end);
   ДвоичныеДанные = WSПрокси.getFile(0);
   ДвоичныеДанные.Записать("C:\\test.xml_enc");    
КонецПроцедуры
26 kosts
 
09.07.13
15:19
Попробуй справочник заблокировать


Попытка
   Объект.Заблокировать();
Исключение
   Текст = "ru = ""Не удалось заблокировать объект"";"
          + " en = ""Can't lock the object""";
   Предупреждение(НСтр(Текст) " """ + Объект + """!
          |"+ ОписаниеОшибки());
КонецПопытки;

27 D_Sergeevich
 
09.07.13
15:33
А когда снимается блокировка? когда будит выход из процедуры?
28 Fragster
 
гуру
09.07.13
15:42
(24) транзакцию-то добавь
29 D_Sergeevich
 
09.07.13
16:46
(28) При попытки вызвать метод вторым пользователем возникает Ошибка (Конфликт блокировок при выполнении транзакции. Превышено максимальное время ожидания предоставления блокировки)
&НаСервере
Процедура ПодключениеКВебСервису(data_start, data_end, acc_source, name_source)
   НачатьТранзакцию(РежимУправленияБлокировкойДанных.Управляемый);
   Блокировка = Новый БлокировкаДанных;
   ЭлементБлокировки = Блокировка.Добавить("Константа.Блокировка");
   ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
   Блокировка.Заблокировать();
   
   WSОпределение = Новый WSОпределения("C:/Service.wsdl");
   WSПрокси = Новый WSПрокси(WSОпределение,"http://tempuri.org/","Service1","Service1");
   WSПрокси.Пользователь = "***";
   WSПрокси.Пароль = "***";
   
   Данные = WSПрокси.GetDataWcf(name_source, acc_source, data_start, data_end);
   ДвоичныеДанные = WSПрокси.getFile(0);
   ДвоичныеДанные.Записать("C:\\test.xml_enc");
   ЗафиксироватьТранзакцию();    
КонецПроцедуры
30 Fragster
 
гуру
09.07.13
16:51
(29) так и задумано - чтобы твой второй не ждал бесконечно. если надо бесконечно - то можно (а) сииииильно увеличить время ожидания блокировки, например с помощью УстановитьВремяОжиданияБлокировкиДанных() (б) пытаться установить блокировку в попытке в цикле (там надо вместе с НачатьТранзакцию(), если что)
31 D_Sergeevich
 
09.07.13
16:56
(30) А нельзя сделать так чтобы выводилось предупреждение? типа (В данный момент идет получение данных для такого то пользователя, попробуйте повторить попытку через ~30 сек.)
32 Fragster
 
гуру
09.07.13
17:06
(31) кто я такой, чтобы запрещать так сделать?
33 D_Sergeevich
 
09.07.13
17:18
(32) )) Ну вообще то я имел введу как так сделать?
34 Fragster
 
гуру
09.07.13
17:23
Попытка ... исключение Сообщение/возврат ошибки КонецПопытки