Что нового

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

joiner

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

El Panda

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

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
это функция отправки сообщения:
Код:
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

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

joiner

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

beve

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

joiner

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

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Задержку регулировать можешь в 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!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Александр [?]
разницы нет. что адлибом что просто указыаешь функцию - результат один
Вот пример как это сделать:

Код:
#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

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
CreatoR сказал(а):
Вот пример как это сделать...

А какая разница в данном случае между SetTimer() и AdlibEnable()?

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

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
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

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

;)
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied [?]
AutoIt не поддерживает многопоточность
Я не говорю что поддерживает, многопоточность тут ни при чём.

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

joiner

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

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

ynbIpb

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

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Александр сказал(а):
...предложенный код в этой теме лишь пример того, как вызвать одну функцию во время работы другой, но не пример одновременной работы функций.

Я предлагаю тебе сначала попробывать это, а потом делать выводы.
 
Автор
joiner

joiner

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

Yashied

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

CreatoR

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

joiner

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

Код:
While 1
	Sleep(100)


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

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