Что нового

Одновременная работа двух и более функций

joiner

Модератор
Локальный модератор
как при нажатии одной кнопки в GUI заставить работать две функции одновременно а не последовательно?
уточню: одна функция отвечает за отсылку сообщения, а другая это функция (она привязана к GUICtrlCreateProgress) отображения прогресса- не отображает точно, а просто сигнализирует что идет отправка (этого достаточно).
основная функция это отправка сообщения. когда она перестает работать по какой либо причине нужно чтобы и функция отображения процесса тоже отключилась.
пробовал вложением функции прогресса в отсылку сообщения, но на ней все и зацикливается..
 

El Panda

Продвинутый
Многопоточности в AutoIt'е нет. К сожалению :(
Дай примеры кода, посмотрим что можно сделать.
 
Автор
joiner

joiner

Модератор
Локальный модератор
это функция отправки сообщения:
Код:
Func _Message()
	$oIE = _IECreate(GUICtrlRead($ADRESS), 0, 0)
	If @error Then
		MsgBox(0, "Отчет", "Ошибка браузера")
		_IEQuit($oIE)
		$oForm = _IEFormGetCollection($oIE, 1)
		If @error Then
			MsgBox(0, "Отчет", "Сообщение невозможно отправить")
			_IEQuit($oIE)
			ElseIf Not @error Then
			$oLogin = _IEFormElementGetObjByName($oForm, "vb_login_username")
			$oPass = _IEFormElementGetObjByName($oForm, "vb_login_password")
			_IEFormElementSetValue($oLogin, GUICtrlRead($LOGIN))
			_IEFormElementSetValue($oPass, GUICtrlRead($PASSWORD))
			_IEFormSubmit($oForm, 1)
			_IELoadWait($oIE, 10000)
			$oMessage = _IEFormGetCollection($oIE, 3)
			$oText = _IEFormElementGetObjByName($oMessage, "message")
			If @error Then
				MsgBox(0, "Отчет", "Сообщение не создано.Логин или пароль не верен")
				_IEQuit($oIE)
			Else
				_IEFormElementSetValue($oText, GUICtrlRead($MESSAGE))
				_IEFormSubmit($oMessage, 1)
				_IEQuit($oIE)
				MsgBox(0, "Отчет", "Cообщение отправлено")
			EndIf
		EndIf
	EndIf
EndFunc

это функция для отображения прогресса ( говорит о том что отправка сообщения в дествии):
Код:
Func _Progress()
	While 1
	$wait = 20
      $s = 0
    For $i = $s To 100

      GUICtrlSetData ($Progress,$i)

      Sleep($wait)
  Next
  WEnd
  EndFunc
 

beve

Осваивающий
Для функции прогресса всегда полезно использовать функцию AdlibEnable, а в когда не нужно будет то вызываем AdlibDisable ().
 
Автор
joiner

joiner

Модератор
Локальный модератор
beve сказал(а):
Для функции прогресса всегда полезно использовать функцию AdlibEnable, а в когда не нужно будет то вызываем AdlibDisable ().
разницы нет. что адлибом что просто указыаешь функцию - результат один
 

beve

Осваивающий
Тогда используй ProgressOn, а в определенные моменты просто добавляй через ProgressSet статус выполнения, а в конце ProgressOff().
 
Автор
joiner

joiner

Модератор
Локальный модератор
beve сказал(а):
Тогда используй ProgressOn, а в определенные моменты просто добавляй через ProgressSet статус выполнения, а в конце ProgressOff().
это не то.. мне нужно отображение условного прогресса в созаднном окне.. я выше писал
 

Yashied

Модератор
Команда форума
Глобальный модератор
Задержку регулировать можешь в AdlibEnable('_StateUpdate', 500).

Код:
#Include <GUIConstantsEx.au3>

Global $Percent = 0

GUICreate('MyGUI', 300, 140)
$Progress = GUICtrlCreateProgress(20, 40, 260, 20)
$Button = GUICtrlCreateButton('Stop', 115, 100, 70, 23)
GUISetState()

AdlibEnable('_StateUpdate', 500)

While 1
	$Msg = GUIGetMsg()
	Switch $Msg
		Case $GUI_EVENT_CLOSE
			ExitLoop
		Case $Button
			GUICtrlSetState($Button, $GUI_DISABLE)
			AdlibDisable()
	EndSwitch
WEnd

Func _StateUpdate()
	$Percent += 10
	If $Percent > 100 Then
		GUICtrlSetState($Button, $GUI_DISABLE)
		AdlibDisable()
		Return
	EndIf
	GUICtrlSetData($Progress, $Percent)
EndFunc   ;==>_StateUpdate
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Александр [?]
разницы нет. что адлибом что просто указыаешь функцию - результат один
Вот пример как это сделать:

Код:
#include <GUIConstantsEx.au3>
;

Opt("GUIOnEventMode", 1)

Global $ahCallBack[2], $iPrecent

$hGUI = GUICreate("ProgressBar", 400, 300)
GUISetOnEvent($GUI_EVENT_CLOSE, "_Main_Events")

$Progress = GUICtrlCreateProgress(10, 10, 300, 22)
$Status_Label = GUICtrlCreateLabel("0%", 330, 30, 30, 20)

$Button = GUICtrlCreateButton("Start",150,100,50,20)
GUICtrlSetOnEvent(-1, "_Main_Events")

GUISetState()

While 1
	Sleep(100)
	
	If $iPrecent > 0 Then
		;Тут мы вызываем нашу функцию
		Call("_SomeFunction_Proc")
	EndIf
WEnd

Func _Main_Events()
	Switch @GUI_CtrlId
		Case $GUI_EVENT_CLOSE
			_CallBack_Free($ahCallBack)
			Exit
		Case $Button
			If GUICtrlRead($Button) = "Stop" Then
				GUICtrlSetData($Button, "Start")
				_CallBack_Free($ahCallBack)
			Else
				GUICtrlSetData($Button, "Stop")
				$ahCallBack = _CallBack_Init("_SetProgress_Proc", 10)
			EndIf
	EndSwitch
EndFunc

Func _SomeFunction_Proc()
	While $iPrecent > 0
		Sleep(50)
		ConsoleWrite("Наша функция работает на ряду с прогрессом :)... " & $iPrecent & @CRLF)
	WEnd
EndFunc

Func _SetProgress_Proc()
	$iPrecent += 1
	
	GUICtrlSetData($Progress, Round($iPrecent / 3))
	GUICtrlSetData($Status_Label, Round($iPrecent / 3) & "%")
	
	If $iPrecent > 300 Then
		$iPrecent = 0
		
		GUICtrlSetData($Status_Label, "100%")
		GUICtrlSetData($Button, "Start")
		_CallBack_Free($ahCallBack)
		
		$ahCallBack = 0
		Dim $ahCallBack[2] = [-1, -1]
	EndIf
EndFunc

Func _CallBack_Init($sFuncName, $iTime, $sParam="")
	Local $hCallBack = DLLCallbackRegister($sFuncName, "int", $sParam)
	
	Local $aTimer = DllCall("user32.dll", "uint", "SetTimer", _
		"hwnd", 0, "uint", 0, "int", $iTime, "ptr", DllCallbackGetPtr($hCallBack))
	
	Local $ahCallBack[2] = [$hCallBack, $aTimer[0]]
	
	Return $ahCallBack
EndFunc

Func _CallBack_Free($ahCallBack)
	If $ahCallBack[0] <> -1 Then DllCallbackFree($ahCallBack[0])
	If $ahCallBack[1] <> -1 Then DllCall("user32.dll", "int", "KillTimer", "hwnd", 0, "uint", $ahCallBack[1])
EndFunc
 

Yashied

Модератор
Команда форума
Глобальный модератор
CreatoR сказал(а):
Вот пример как это сделать...
А какая разница в данном случае между SetTimer() и AdlibEnable()?

С AdlibEnable() в x2 раза короче.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Yashied [?]
какая разница в данном случае между SetTimer() и AdlibEnable()?
http://www.autoitscript.com/autoit3/docs/functions/AdlibEnable.htm
The adlib function should be kept simple as it is executed often and during this time the main script is paused.
Другими словами, если в вызываемой функции (той где нужно работать с IE) будет нечто блокирующее (например цикл), то прогресс остановится ;)
 

Yashied

Модератор
Команда форума
Глобальный модератор
CreatoR, AutoIt не поддерживает многопоточность, и SetTimer() будет работать так же, как и AdlibEnable(). Поставь в функцию Sleep(200) и сам убедишься.

;)
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Yashied [?]
AutoIt не поддерживает многопоточность
Я не говорю что поддерживает, многопоточность тут ни при чём.

SetTimer() будет работать так же, как и AdlibEnable()
В этом конкретном случае возможно, но у Timer'ов свои плюсы. Например при перетаскивании окна прогресс будет продолжать свою работу :smile:
 
Автор
joiner

joiner

Модератор
Локальный модератор
CreatoR сказал(а):
Вот пример как это сделать:
если следовать этому примеру, то получается так: как только процент прогресса выше 1 вызывается другая функция, но при этом функция прогресса останавливается пока не отработает вызванная до конца или до первой ошибки, а потом функция прогресса завершается.
нужно чтобы работали обе одновременно..
я хочу чтобы когда начнется отправка сообщения через функцию _Message() одновременно заработала функция _Progress(). которая видимым образом будет говорить что идет отправка

предложенный код в этой теме лишь пример того, как вызвать одну функцию во время работы другой, но не пример одновременной работы функций.
 

ynbIpb

Скриптер
создай отдельный скрипт, который будет управлять прогрессом в основном скрипте. Конечно будет 2 исполняемых файла, но зато как бы многопоточность ;)
 

Yashied

Модератор
Команда форума
Глобальный модератор
Александр сказал(а):
...предложенный код в этой теме лишь пример того, как вызвать одну функцию во время работы другой, но не пример одновременной работы функций.
Я предлагаю тебе сначала попробывать это, а потом делать выводы.
 
Автор
joiner

joiner

Модератор
Локальный модератор
Yashied сказал(а):
Я предлагаю тебе сначала попробывать это, а потом делать выводы.
после пробы и написал.. видно как начинается прогресс. как он останавливается . происходит выполнение вызванной функции и прогресс потом продолжается..
 

Yashied

Модератор
Команда форума
Глобальный модератор
Единственное, что в данном случае можно сделать, это поместить функцию _Message() в отдельный скрипт и запускать его в нужный момент. В качестве параметров передавать логин, пароль и т.д. Результат работы можно оценить, например, по ответу этого скрипта - ConsoleWrite(). В вызывающем скрипте - StdoutRead(). У меня так работает программа для закачки файлов на FTP.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Александр [?]
происходит выполнение вызванной функции и прогресс потом продолжается
Значит что-то блокирует скрипт в этой функций. Что именно она делает?
 
Автор
joiner

joiner

Модератор
Локальный модератор
[?]
CreatoR сказал(а):
Что именно она делает?
на предыдущей странице я указал функцию.. это отсылка сообщений. просто хотелось чтобы была индикация отсылки ввиде прогрессбара. это не критичная задача.. просто удобно.. видишь что работает..
в предложенном варианте в моменте

Код:
While 1
	Sleep(100)


	If $iPrecent > 0 Then
		;Тут мы вызываем нашу функцию
		Call("message")
	EndIf
WEnd

у меня еще куча Case.. вобщем либо работает одно, либо другое.. вместе ну ни как.
не хотелось отдельных скриптов, видимо придется..
 
Верх