Что нового

Возврат к началу цикла по таймеру

valdur2000

Знающий
Сообщения
155
Репутация
7
Здравствуйте уважаемые, прошу помощи с решением следующей задачи, приведу скелет кода:

Код:
_IECreate ;Создаю окно IE
For $i=1 To 10
Тут проверка на существование окна IE, если нет, то создать заново
Тут само тело с тыкалками, проверялками, подциклами... строк на 500
_FileWriteLog ;Пишу в логфайл строку, время и что и как прошло
Next

непосредственно вопрос: всего не предусмотришь, поэтому надо сделать таймер прохода цикла скажем в 3 минуты. если за три минуты $i не прирос на единицу, значит возврат на начало цикла. Попутно еще вопрос, а можно ли вернуться туда, куда я захочу и продолжить выполнение кода откуда я захочу. как в старом бейсике команда GoTo? Заранее благодарю.
 

sngr

AutoIT Гуру
Сообщения
1,010
Репутация
408
Goto в autoit больше нет, как таймер можно использовать
Код:
_Timer_Init   
_Timer_Diff.
 

sngr

AutoIT Гуру
Сообщения
1,010
Репутация
408
может вот так:
Код:
#include <Timers.au3>
While 1
For $i=1 To 10
$starttime = _Timer_Init()
;код
if _f ()=1 Then ExitLoop
;много строк кода
if _f ()=1 Then ExitLoop
;много строк кода
if _f ()=1 Then ExitLoop
Next
WEnd
Func _f ()
	if _Timer_Diff($starttime) >= 180000 And $i=1 Then Return 1
EndFunc
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
Код:
if _f ()=1 Then ExitLoop
;много строк кода
if _f ()=1 Then ExitLoop

на сколько я понимаю проверка времени будет происходить в If'ах, а если зависнет как раз в
много строк кода
какой-нибудь pixelgetcolor?
 

sngr

AutoIT Гуру
Сообщения
1,010
Репутация
408
pixelgetcolor можно вынести в отдельный скрипт и проверять время от его запуска до значения таймера и в случае привышения пришибать этот отдельный скрипт.
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
sngr
sngr сказал(а):
$i будет приращиваться, так как критерии для For установлены.
В проверках задано условие:
if _Timer_Diff($starttime) >= 180000 And $i=1 Then 1
Старт!
Первый проход :
$i = 1
($starttime) >= 180000
Условие не выполнено!
То есть, первый цикл отработал нормально все три условия.
Второй проход :
$i = 2
($starttime) >= 180000
Условие никогда не будет выполнено, даже если код между условиями не отработал корректно!
То есть, код лимит превысил, а $i уже не 1.
 

sngr

AutoIT Гуру
Сообщения
1,010
Репутация
408
Код:
#include <Timers.au3>
While 1
For $i=1 To 10
$starttime = _Timer_Init()
;код
if _f ()=1 Then ExitLoop
;много строк кода
if _f ()=1 Then ExitLoop
;много строк кода
if _f ()=1 Then ExitLoop
Next
WEnd
Func _f ()
    if _Timer_Diff($starttime) >= 180000 Then Return 1
EndFunc

Вот так будет вернее. При втором проходе цикла, таймер запустится снова (как я это понимаю) и 2 условие будет ненужно.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
проще задать переменную инкремента в начальное значение при невыполнении нужных условий.
Код:
For $i = 1 to 10
    If Not something() Then $i = 0; Что-то не случилось? начни цикл заново. 0 или 1 точно не скажу, надо проверить на примере
Next
 

sngr

AutoIT Гуру
Сообщения
1,010
Репутация
408
Код:
For $i = 1 to 10
    If Not something() Then $i = 0; Что-то не случилось? начни цикл заново. 0 или 1 точно не скажу, надо проверить на примере
Next
При $i=0 цикл не начнётся заново - изначальным станет количество проходов. Весь код ниже $i=0 будет спокойно исполнятся, что, как я понимаю, не нужно.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
valdur2000,
Можно так попробовать.
Код:
Global $iTimeOut = 30000, $iStart, $iCount

HotKeySet('{Esc}', '_Exit')

For $i = 1 To 10
	$iStart = TimerInit()
	For $j = 1 To 10
		ToolTip('$j = ' & $j & @LF & StringFormat('%.2f sec', TimerDiff($iStart) / 1000), 0, 0, '$i = ' & $i)
		Sleep(Random(500, 1500, 1))
	Next
	If _ContinueLoop() Then
		$i -= 1
		$iCount += 1
		Beep(100, 20)
		ContinueLoop
	EndIf
	For $q = 11 To 20
		ToolTip('$q = ' & $q & @LF & StringFormat('%.2f sec', TimerDiff($iStart) / 1000), 0, 0, '$i = ' & $i)
		Sleep(Random(500, 1500, 1))
	Next
	If _ContinueLoop() Then
		$i -= 1
		$iCount += 1
		Beep(100, 20)
		ContinueLoop
	EndIf
	For $w = 21 To 30
		ToolTip('$w = ' & $w & @LF & StringFormat('%.2f sec', TimerDiff($iStart) / 1000), 0, 0, '$i = ' & $i)
		Sleep(Random(500, 1500, 1))
	Next
	If _ContinueLoop() Then
		$i -= 1
		$iCount += 1
		Beep(100, 20)
		ContinueLoop
	EndIf
	For $x = 31 To 40
		ToolTip('$x = ' & $x & @LF & StringFormat('%.2f sec', TimerDiff($iStart) / 1000), 0, 0, '$i = ' & $i)
		Sleep(200)
	Next
	Beep(200, 300)
Next
MsgBox(64, 'Info', 'Все :)' & @LF & 'Не хватило времени раз: ' & $iCount)

Func _ContinueLoop()
	Return (TimerDiff($iStart) >= $iTimeOut)
EndFunc   ;==>_ContinueLoop

Func _Exit()
	Exit
EndFunc   ;==>_Exit
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
sngr [?]
При $i=0 цикл не начнётся заново
как не начнется? начнется.

Весь код ниже $i=0 будет спокойно исполнятся, что, как я понимаю, не нужно
да, будет. поэтому можно эту проверку поставить в самый конец.

а вообще, в одним потоке (читай в одном скрипте) подобную проверку на зависание не сделать, т.к. все замеры будут происходить после выполнения операций. поэтому тут только в отдельный скрипт.
 

Dm666

Осваивающий
Сообщения
221
Репутация
48
А можно еще через AdlibRegister извратиться ;)
Делаем 2 одинаковых скрипта Script1.exe и Script2.exe, кладем в один каталог. Скрипты типа такого:
Код:
Sleep(1000) ; Пауза на всякий случай
HotKeySet("{Esc}", "_Exit")

SplashTextOn("", "Running " & @ScriptName & @CRLF & "ESC - Exit")
Global $sScript1 = @ScriptDir & "\Script1.exe"
Global $sScript2 = @ScriptDir & "\Script2.exe"
Global $iTestCounter = 1
AdlibRegister("_Test", 5000) ; Задаем интервал проверки $i, здесь 5 секунд

For $i = 1 To 10
	MouseMove(500, 500, 90) ; типа основной скрипт, что-то там делает
	MouseMove(500, 400, 90) ; типа основной скрипт, что-то там делает
	If $i = 3 Then
		SplashOff()
		SplashTextOn("", "Running " & @ScriptName & @CRLF & "ESC - Exit" & @CRLF & "Здесь мы как будто повисли")
		WinWaitActive("asdasd") ; имитируем зависание на 3м круге
	EndIf
	
Next

Func _Test()
	$iTestCounter += 1 ; счетчик запусков тестовой функции
	If $iTestCounter > $i Then ; $i отстает, значит повисли
		If ProcessExists("Script1.exe") Then ; restart
			Run($sScript2)
			ProcessClose("Script1.exe")
		Else
			Run($sScript1)
			ProcessClose("Script2.exe")
		EndIf
	EndIf
EndFunc

Func _Exit()
	Exit
EndFunc

Главное грамотно рассчитать интервал проверок, и будет работать
 
Автор
V

valdur2000

Знающий
Сообщения
155
Репутация
7
Спасибо всем огромное за совместный мозговой штурм. за ночь у меня родился свой вариант, который может еще сыроват и красив как гадкий утенок, но работает и позволяет взять зависание под контроль, со сбросом цикла. Перед началом надо открыть блокнот в левом верхнем углу.
Код:
#include <file.au3>
#Include <Date.au3>
dim $x,$x1=1
Func proverkadaty() ;тут будет проверяться 5 секунд ничегонеделания
	$file = "c:\autoit\test.txt" ;лог куда пишутся удачные даты и от последней отсчитывается  5 секунд
	$lines = _FileCountLines($file) ; кол-во строк в логе
	$time_old = FileReadLine($file,$lines) ; поиск последней записи даты
	$time = _NowCalc() ;получение даты сеюминутной
	$iDateCalc = _DateDiff( 's',$time_old,$time) ; сравнение этих дат в секундах
	if $iDateCalc >= 5 ; Then если разница более 5 сек, то...
		$x1=0 ;счетчик цикла сбрасываем на ноль
		$x=$x1
		MouseClick("left",51,62,1) ;клик в блокнот
		Send("aaa") ;отправка пароля
	;MsgBox(0,"","nachalo   " & $time_old & @CRLF & "sejchas   " & $time & @CRLF & "diff     " & $iDateCalc)
Else
	EndIf
EndFunc ;функция закончилась

MsgBox (0,"","nachalo") ; код начинается с флажка "начало"
AdlibRegister("proverkadaty",6000) ;вот Adlib, секущий каждые 6 сек, не появятся ли фашики
For $x=$x1 To 5 ;от 1 до 5
	ToolTip($x,505, 97) ;тут видно какая итерация выполняется на данный момент
While 1
	PixelSearch (13,55,35,68,0x000000) ; по заданию в блокноте ждется любой символ 
	If Not @error Then
		MsgBox (0,"","text") ;если появился, то msgbox ("text")
		ExitLoop
	Else
		Sleep(100)
	EndIf
WEnd
$time = _Date_Time_GetLocalTime() ; после каждой итерации пишем дату и время в лог
_FileWriteLog("c:\autoit\test.txt", $time)

Next


Результат: Adlib работает, счетчик сбрасывается. Может понапутано немного и лишку написал, это от неопытности.
 
Верх