Книга знаний

1С:Предприятие / Администрирование / Производительность

Перепроведение документов в 1С:Предприятие без блокировки других пользователей

Статья описывает способ "безопасного" проведения документов при работающих сетевых или SQL-
<br><br><br><br><br>пользователях. Дело в том, что если проводить документы без пауз, то работа остальных
<br><br><br><br>пользователей в
<br><br><br><br><br>1С будет заблокирована. Статья содержит ссылку на внешнюю компоненту с исходным кодом, а также
<br><br><br><br><br>содержит другие рецепты, как сделать паузу без использования внешних компонент.
Автор статьи: romix | Редакторы: Лёвыч, Fragster, coding, mikecool
Последняя редакция №14 от 07.06.11 | История
URL: http://kb.mista.ru/article.php?id=98

Ключевые слова: sleep, транзакция, блокировка, пауза, проведение, документов, компонентофобия


Для того, чтобы транзакции пользователей не «висели» в бесконечном (или, скорее, конечном) цикле, а
могли все-таки выполниться, алгоритм перепроведения документов должен включать паузы (т.е.
необходимо проводить документы не все время, а с промежутками). Тогда пользователи смогут «вставить»
свои собственные транзакции, и продолжить, без значительных помех, свою работу.  

К сожалению, в 1С нет аналога системной функции sleep, которая в системе Windows (и, кстати,
изначально - в Unix) делает паузу в миллисекундах, не нагружая при этом процессор (точнее, процессор
все равно работает, но при этом выполняются другие задачи в многозадачной операционной среде). Для
этого, если вы не ищете легких путей, используйте внешнюю компоненту, которая реализует системный
вызов sleep().

Пример внешней компоненты (с исходным кодом) можно скачать по адресу:
http://x-romix.narod.ru/Sleep.rar

Если у вас лекарственная идиосинкразия к внешним компонентам и COM-объектам, есть и другие способы
сделать паузу. Один из самых простых - Предупреждение() с таймаутом в секундах (второй параметр
метода Предупреждение):

Процедура Проведение()
  док=СоздатьОбъект(«Документ»);
  док.ВыбратьДокументы(НачДата, КонДата);
  Пока док.ПолучитьДокумент()=1 Цикл
    док.Провести();
    Предупреждение(«Ждем 3 секунды…», 3);
  КонецЦикла;
КонецПроцедуры


Звезочет: предупреждение не срабатывает, если окно теряет фокус ввода. То же самое, для
диалога ВводЧисла. А вот для ВводСтроки - таймаут работает! ;))
v8: Аналог Sleep()



//делает паузу с округлением до целого числа секунд - 1000, 2000 и т.д.
//Использует ВводСтроки с таймаутом, который работает даже если окно теряет фокус ввода.
Процедура sleep(ms)
    стр="Ожидание "+ТекущееВремя();
    Состояние(стр);
    сек=цел(ms/1000);
    ВвестиСтроку(стр, стр, 100, 0, сек);
КонецПроцедуры    




Для организации цикла ожидания можно также воспользоваться (недокументированной) функцией
_GetPerformanceCounter() – это счетчик времени в миллисекундах, или документированной – ТекущееВремя
() – с точностью до секунды. Но при этом потребуется «крутить» цикл без пауз, который, как известно,
потребляет 100% ресурсов одного процессора (что может сказаться на производительности работы
пользователей, например, в терминальном режиме).

Лёвыч:
для тех, у кого идиосинкразия только к ВК, но не к ActiveX-объектам в целом, могу предложить такой
велосипед:
Процедура глВремя_Задержка(чСекунд) Экспорт

    ИмяПутьСкрипта = КаталогПользователя()+"sleep.js";
    
    Скрипт = СоздатьОбъект("Текст");
    
    Скрипт.ДобавитьСтроку("WScript.Sleep("+Строка(1000*чСекунд)+");");
    
    Скрипт.Записать(ИмяПутьСкрипта);
    
    cmdLine="wscript.exe "+ИмяПутьСкрипта;
    
    WshShell = СоздатьОбъект("WScript.Shell");
    
    WshShell.Run(cmdLine, 0, -1);

КонецПроцедуры



Fragster: Для паузы можно использовать более короткий вариант:
Процедура глПауза(Сек)
    scr = СоздатьОбъект("WScript.Shell");
    scr.Run("sleep "+СокрЛП(Число(Сек)),0,1);
КонецПроцедуры;

Ну а если у кого-то нету sleep.exe, то
Процедура глПауза(Сек)
    scr = СоздатьОбъект("WScript.Shell");
    scr.Run("ping 127.0.0.1 -n "+СокрЛП(Число(Сек)+1),0,1);
КонецПроцедуры;


Еще одна функция глПаузы:

 Процедура глПауза(МСекунды)
     Перем Таймер;
     Таймер     = _GetPerformanceCounter() + МСекунды;
     Пока Таймер > _GetPerformanceCounter() Цикл
         //Состояние(Таймер);
     КонецЦикла;
КонецПроцедуры


Метод организации паузы на сервере 1С под управлением любой(?) ОС. Я использовал для Линух-систем.
Спасибо за помощь товарищу Fragster / http://forum.mista.ru/users.php?id=28765
Вот вся моя процедура паузы:

Процедура Пауза(КоличествоСекунд = 1) Экспорт
#Если Клиент Тогда

    // эта часть практ. аналогична Процедура глПауза(Сек), описанной выше
    scr = Новый COMОбъект("WScript.Shell");
    scr.Run("ping 127.0.0.1 -n " + (КоличествоСекунд + 1), 0, 1);
    
#ИначеЕсли Сервер Тогда

    
    HTTP = Новый HTTPСоединение(<адрес сервера с поднятым пхп>);
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла();
    HTTP.Получить("pause.php", ИмяВременногоФайла, "sec:" + КоличествоСекунд);    
    Попытка
        УдалитьФайлы(ИмяВременногоФайла);
    Исключение
    КонецПопытки;
    
#КонецЕсли

КонецПроцедуры


требуется - сервер с поднятым пхп и в %wwwroot% кладется pause.php такого содержимого:
<?php
sleep($_GET['sec']); //тут я ушел от оригинала и заменил имя параметра
?>
обсуждение этого метода велось в ветке v8: v8: Как организовать паузу на сервере под линухом? - решено
как человеку далекому от веб-программирования, кажется, что файл pause.php можно располагать где угодно, лишь бы указать к нему полный путь от %wwwroot%.
Замечу - метод требует проверки на вашей версии php, поскольку возможны варианты в передаче параметра в функцию sleep.

Описание | Рубрикатор | Поиск | ТелепатБот | Захваченные статьи | Установки | Форум
© Станислав Митичкин (Волшебник), 2005-2025 | Mista.ru

Яндекс.Метрика