gifts2017

Реализация паузы выполнения кода, используя Wscript

Опубликовал Максим Синяков (Alximikkk) в раздел Программирование - Практика программирования

Мне понадобилось реализовать паузу в одном алгоритме, и пауза должна была быть не более полусекунды.
Поиски в интернете особо не удались, т.к. варианты либо кривы, либо не совсем оптимальны.

Начну с того, что я нашел и почему мне это не подошло. Мои требования были такими, необходимо было остановить выполнение кода на 0.1-0.5 секунды, клиент-серверный вариант работы, управляемые формы, тонкий клиент, пауза на клиентской части.

1) Первый вариант, который я нашел, был таким:

Процедура Спать(Время)
    Если Время = 0 Тогда
        Возврат
    КонецЕсли;
    Сигнатура = Формат(ТекущаяДата(), "ДФ=yyyyMMddhhmmss");
    ПутьСкрипта = КаталогВременныхФайлов()+"SleepScript"+Сигнатура+".vbs";
    СкриптФайл = Новый ТекстовыйДокумент;
    СкриптФайл.ДобавитьСтроку("WScript.Sleep("+Формат(Время*1000, "ЧГ=0")+")");
    СкриптФайл.Записать(ПутьСкрипта, КодировкаТекста.OEM);
    WSHShell = Новый COMОбъект("WScript.Shell");
    WSHShell.Run("wscript.exe """+ПутьСкрипта+"""", 0, Истина);
    УдалитьФайлы(ПутьСкрипта);
КонецПроцедуры

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

2)Второй вриант был довольно таки удобный, и подходил бы мне, если бы можно было поставить задержку менее секунды:

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

Такой вариант паузы я использовал еще в .bat файлах. Но он не подходит из-за минимального времени в 1 секунду.

3)Вариант с циклом и проверкой времени был отметен, как ересь, в связи с нагрузкой на процессор, и минимальным временем в 1 секунду.

4)Этот вариант вообще достаточно странный, я уж решил что это именно то, что мне нужно, но потом посмотрел и понял, что нужен некий файлик sleep. Без него выдаётся ошибка  0x80070002. А качать из интернета файл sleep.exe не очень хочется.

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

5)Был еще вариант с предупреждением и выбором из списка с таймером, но там опять же минимальная пауза 1 сек + еще окна лишние.

В итоге я понял, что нормальной реализации с помощью языка 1С нету, так как в большинстве случаев используется подключение Wscript.Wshell, и видимо не просто так. Но использовать первый вариант я совершенно не хотел, из за записи файла на диск. 

У меня был небольшой опыт работы c VBScript, поэтому я знал, что в скрипт можно переадавать параметры. Этим я  и воспользовался.  Был написан простой скрипт ожидания, который принимал один параметр:

wscript.sleep wscript.arguments(0)

Сделать это очень просто: открываем блокнот, вставляем строчку , которая написана выше, жмем "Сохранить как...",  и сохраням как sleep.vbs.

Этот файл необходимо положить на сервер(для вызова на сервере) и на клиент(для вызова на клиенте), в моём случае(сервер терминалов), я положил файл на оба сервера(терминальный и на сервер 1С).

Теперь у нас есть скрипт который будет ждать столько, сколько мы скажем, осталось его вызвать из программы.

Вызов происходит в две строчки кода:

Процедура ОбработкаОжидания(Секунда)
    scr = Новый COMОбъект("WScript.Shell");
    scr.Run("Wscript.exe ""C:\temp\sleep.vbs"" "+секунда*1000,0,1);
КонецПроцедуры

Я положил процедуру в общий модуль на клиенте, и в общий модуль на сервере, так же в параметр задал ПутьХраненияФайла. Вот таким образом с помощью Wscript, без постоянного создания файлов скрипта можно реализовать паузу в работе кода с минимальным значением ~0,001 секунда.

Скачать файлы

Наименование Файл Версия Размер
sleep.vbs 17
.vbs 0,04Kb
19.06.13
17
.vbs 0,04Kb Скачать

См. также

Подписаться Добавить вознаграждение
Комментарии
2. Максим Синяков (Alximikkk) 21.06.13 17:17
(1) sCHTASS, я же перечислил варианты, которые не подошли, и в итоге привел пример варианта, который адекватно работает и выполняет все необходимые мне функции, и которого еще не было, по крайней мере я не нашел. Многие предлагают создавать файл на диске прямо во время исполнения кода , но этот вариант мне не подходит. Поэтому я описал своё видение этого решения, а так же альтернативные варианты.
3. Konstantin Konstantin (KonstB) 21.06.13 23:11
(2) Alximikkk,

Чем же Вам не подошел вариант с созданием файла... Вы так и так используете файл. НО Ваш вариант, который через параметр меннее "жизниспособный", ибо
- удалили файл
- файл не досупен
- порезали права
- подключился на другой терминал (а профиль не мигрировал), а файл лежит не в шаре...
и все капут, задержки нет...

Почитайте (или обновите платформу) про ТекущаяУниверсальнаяДатаВМиллисекундах() (с помощью этого...)
4. Максим Синяков (Alximikkk) 22.06.13 22:29
(3) KonstB, не подошел мне этот вариант, потому что необходимо каждый раз создавать новый файл. Это конечно не очень критично, и я бы наверное использовал его, так как он на самом деле более устойчив при постоянно изменяющейся рабочей обстановке. Мой же вариант предполагает, что рабочая обстановка более менее устойчива, к тому же он быстрее и оптимальнее, что немаловажно. Вот например, при варианте с созданием, нам вначале нужно создать текст скрипта, перезаписать файл в нашей ФС, и выполнить скрипт; В моем же варианте достаточно просто выполнить скрипт, и если предположить, что скрипт всегда доступен, то мой вариант работает оптимальнее. Удаление файла решается правами доступа, и тут скорее "права доступа" работают в пользу моего варианта, так пользователю надо иметь только право на чтение файла, в варианте с созданием - необходимо право так же и на запись(я понимаю, что скорее всего будет использован каталог пользователя, на который он имеет права, но всё же). Можно конечно проверять наличие файла, но это тоже не очень гуд.
За ТекущаяУниверсальнаяДатаВМиллисекундах() спасибо, не знал. Я предполагаю, что вы предлагаете циклить и проверять на дату, это конечно более простой с точки зрения разработки и понимая алгоритм, но загружать одно ядро на 100%(ведь пустой цикл будет грузить 1 ядро полностью, так?) даже на 0,1 секунду не очень хочется, ведь пауза подразумевает под собой остановку(паузу) в выполнении, а не нагрузку системы до такого состояния, что она может сожрать все ресурсы сервера)))
5. Данила Елистратов (CagoBHuK) 26.06.13 09:52
1. А что делать, если 1С на Линукс? Почему программисты рассматривают только Windows-машины? Ваш вариант в таком случае работать не будет.
2. Я не знаю, чем не угодило ПодключитьОбработчикОжидания(). Отлично работает во всех конфигурациях 1С от Раруса.
Резюме: незачем изобретать велосипед, тем более который ездит только по рельсам.
6. Максим Синяков (Alximikkk) 26.06.13 10:22
1)Под Линукс не работает, это да, поэтому я и поставил платформу windows. Так же в заголовке быо написано wscript, что подразумевает работу на Windows. С Линуксом просто плотно не работал, поэтому не могу точно сказать, но скорее всего там тоже можно реализовать нечто подобное.(естественно не на Vbscript, а на встроенном языке, или на Python'е например)
2)ПодключитьОбработчикОжидания() не угодил тем, что выполняется он параллельно с кодом, а не останавливает его, к тому же в, вызываемую обработчиком ожидания, процедуру нельзя передавать параметры. Но основное это то, что пауза нужна не для того, чтобы отложить запуск процедуры, а для того, чтобы приостановить выполнение программного кода.
7. Олег Григорьев (baradist) 08.12.13 04:32
(4) Alximikkk, в цикле записывать один и тот же файл, что за извращение?
Кто мешает записать нужный vbs, перед циклом и в цикле использовать его?
8. A M (KrackMan) 13.01.14 03:59
Процедура Пауза(Арг)
Нач = ТекущаяДата();
Кон = ТекущаяДата();
Пока Кон-Нач < Арг Цикл
Кон = ТекущаяДата();
КонецЦикла;
КонецПроцедуры

Арг - в секундах. Если использовать ТекущаяУниверсальнаяДатаВМиллисекундах(), то можно задавать и миллисекундах.
9. Nathan Rothschild (Rothschild) 13.01.14 07:30
(3) KonstB,
(8) KrackMan,
---
1. иногда имеется разделение труда:
обновляют платформу - ОДМИНЫ, а кодят программеры 1С.
и не всегда бывает вообще возможно просто так обновить,
если база крутится например на 8.1.

2. а кто скажет на какой релиз (минимально) надо обновить
чтобы длиннюща радость в виде "ТекущаяУниверсальнаяДатаВМиллисекундах()" появилась ???
10. Nathan Rothschild (Rothschild) 13.01.14 07:34
(1) sCHTASS,
соглашусь с вами, товариш, Федель!
и не только в гугле, но и на Инфостарте:

1С и WSH и WMI. ОТ ТЕОРИИ К ПРАКТИКЕ. Часть I: http://infostart.ru/public/165702/
1С и WSH и WMI. ОТ ТЕОРИИ К ПРАКТИКЕ. Часть II: http://infostart.ru/public/166391/
1С и WSH и WMI. ОТ ТЕОРИИ К ПРАКТИКЕ. Часть III: http://infostart.ru/public/166440/

Практическая реализация:
Обработка 1С:Системный Администратор (WSH&WMI): http://infostart.ru/public/172189/



--------------------------------------------------------------------------------
11. Osiris_ (StaticUnsafe) 28.01.14 10:14
КомандаСистемы("timeout /T 10");
scar-67rus; chilyagin; p1l1gr1m; +3 Ответить 1
12. Александр Топольский (AlexanderKai) 14.11.14 09:56
Интересный эффект при использовании последнего метода(scr.Run("Wscript.exe ""C:\temp\sleep.vbs"" "+секунда*1000,0,1);, другие не использовал) - если поставить 100 секунд, то программой после установления паузы можно спокойно пользоваться дальше.
Интересно, как нибудь заблокировать действия с программой можно?
13. eugenie zheludkov (eugeniezheludkov) 22.01.15 05:36
(8) KrackMan, только ваша функция займет процессор этим циклом, а виндовый sleep как раз таки не занимает процессорное время выполняясь на сервере , отдавая его другим процессам, что бывает очень важно , в тех же регламентных заданиях
14. Игорь Константинович (my_espe) 11.04.16 08:51
(11) Osiris_, - не работает на сервере