<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title><![CDATA[Серый форум &mdash; AHK: Асинхронная отправка нескольких запросов и получение ответов]]></title>
		<link>https://forum.script-coding.com/viewtopic.php?id=11198</link>
		<atom:link href="https://forum.script-coding.com/extern.php?action=feed&amp;tid=11198&amp;type=rss" rel="self" type="application/rss+xml" />
		<description><![CDATA[Недавние сообщения в теме «AHK: Асинхронная отправка нескольких запросов и получение ответов».]]></description>
		<lastBuildDate>Tue, 05 Jan 2016 14:03:17 +0000</lastBuildDate>
		<generator>PunBB</generator>
		<item>
			<title><![CDATA[Re: AHK: Асинхронная отправка нескольких запросов и получение ответов]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=100182#p100182</link>
			<description><![CDATA[<p>Вот, что ответил Lexikos:<br /></p><div class="quotebox"><blockquote><p>It is possible, but not with WaitForResponse(). If you wait for the response, you are essentially making the request &quot;synchronous&quot;.<br />WinHttpRequest does not allow you to assign a function reference as an event handler.<br />ComObjConnect does not support non-dispatch event interfaces like the one WinHttpRequest exposes.<br />infogulch wrote a wrapper which supports async events and another wrapper to facilitate multiple requests.</p></blockquote></div><p><a href="https://github.com/infogulch/WinHttpRequest/blob/master/WinHttpRequest.ahk">https://github.com/infogulch/WinHttpReq … equest.ahk</a><br /><a href="https://github.com/infogulch/AsyncHttp/blob/master/AsyncHttp.ahk">https://github.com/infogulch/AsyncHttp/ … ncHttp.ahk</a></p>]]></description>
			<author><![CDATA[null@example.com (Malcev)]]></author>
			<pubDate>Tue, 05 Jan 2016 14:03:17 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=100182#p100182</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Асинхронная отправка нескольких запросов и получение ответов]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=100160#p100160</link>
			<description><![CDATA[<p><a href="http://forum.script-coding.com/viewtopic.php?id=6877">http://forum.script-coding.com/viewtopic.php?id=6877</a><br />Осталось на автохотки перевести. <img src="//forum.script-coding.com/img/smilies/smile.png" width="15" height="15" /></p>]]></description>
			<author><![CDATA[null@example.com (Malcev)]]></author>
			<pubDate>Mon, 04 Jan 2016 18:01:42 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=100160#p100160</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Асинхронная отправка нескольких запросов и получение ответов]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=100159#p100159</link>
			<description><![CDATA[<p>Для WaitForResponse можно таймаут указать, судя по его описанию, в секундах.</p>]]></description>
			<author><![CDATA[null@example.com (YMP)]]></author>
			<pubDate>Mon, 04 Jan 2016 16:15:37 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=100159#p100159</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Асинхронная отправка нескольких запросов и получение ответов]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=100156#p100156</link>
			<description><![CDATA[<p>У меня только так получается через Msxml2.XMLHTTP:<br />Но у него есть следующие моменты:<br /><a href="https://autohotkey.com/boards/viewtopic.php?f=7&amp;t=9554&amp;p=52984#p52984">https://autohotkey.com/boards/viewtopic … 984#p52984</a><br /></p><div class="codebox"><pre><code>link1 := &quot;http://forum.script-coding.com/viewforum.php?id=13&amp;p=1&quot;
link2 := &quot;http://220454.lv&quot;
loop 2
{
   req%A_Index% := ComObjCreate(&quot;Msxml2.XMLHTTP&quot;)
   req%A_Index%.Open(&quot;GET&quot;,link%A_Index%,true)
   req%A_Index%.onreadystatechange := Func(&quot;Ready&quot;).Bind(A_Index)
   req%A_Index%.send()
}
return
#Persistent

Ready(n) {
    if (req%n%.readyState != 4)  ; Not done yet.
       return
    MsgBox % req%n%.responseText
    return
}</code></pre></div><p>Как это сделать с помощью WinHttpRequest не пойму.<br />Потому что такой код неправильный, так как скрипт зацикливается на загрузке второго несуществующего сайта.<br /></p><div class="codebox"><pre><code>link1 := &quot;http://forum.script-coding.com/viewforum.php?id=13&amp;p=1&quot;
link2 := &quot;http://220454.lv&quot;
ComObjError(false)
#persistent
HttpObj1 := ComObjCreate(&quot;WinHttp.WinHttpRequest.5.1&quot;)
HttpObj2 := ComObjCreate(&quot;WinHttp.WinHttpRequest.5.1&quot;)

HttpObj1.Open(&quot;GET&quot;,link1,true) ;the third parameter means, that it will be working asynchronously
HttpObj1.Send()
SetTimer, HttpObj1AsynchHandler, -1
HttpObj2.Open(&quot;GET&quot;,link2,true)
HttpObj2.Send()
SetTimer, HttpObj2AsynchHandler, -1
Return

OnHttpResponse(HttpObj) {
    MsgBox % HttpObj.ResponseText
}

HttpObj1AsynchHandler:
    HttpObj1.WaitForResponse()
    OnHttpResponse(HttpObj1)
Return
HttpObj2AsynchHandler:
    HttpObj2.WaitForResponse()
    OnHttpResponse(HttpObj2)
Return</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Malcev)]]></author>
			<pubDate>Mon, 04 Jan 2016 15:38:27 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=100156#p100156</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Асинхронная отправка нескольких запросов и получение ответов]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=100154#p100154</link>
			<description><![CDATA[<p>Поток может быть прерван другим потоком, например, по нажатию хоткея.<br /></p><div class="codebox"><pre><code>
Loop
{
    SoundBeep, 500, 300
    SoundBeep, 800, 500
    SoundBeep, 2000, 100
}

F12:: ExitApp
F11:: MsgBox, Перерыв
</code></pre></div><p>Что такое конкурентные запросы, к сожалению, не знаю.</p>]]></description>
			<author><![CDATA[null@example.com (YMP)]]></author>
			<pubDate>Mon, 04 Jan 2016 14:59:32 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=100154#p100154</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Асинхронная отправка нескольких запросов и получение ответов]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=100152#p100152</link>
			<description><![CDATA[<div class="quotebox"><cite>YMP пишет:</cite><blockquote><p>Почему непрерываемый? Как и любой другой, он прерываем между соседними командами.</p></blockquote></div><p>Разве прерываем? Я так и до конца и не освоил threads и всё, что с ними связано. Насколько знаю я - если сделать<br />Loop и внутри поочерёдную проверку объектов, то этот loop будет непрерываемым (только если не добавить во внутрь какое-то доп. условие для прерывания, вроде If GetKeyState(), но тогда обратно мы завершить работу в loop уже не сможем вернуться.<br />Можете код показать с прерываемым циклом, позволяющим делать конкурентные асинхронные запросы к серверу?</p>]]></description>
			<author><![CDATA[null@example.com (Drugoy)]]></author>
			<pubDate>Mon, 04 Jan 2016 14:22:20 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=100152#p100152</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Асинхронная отправка нескольких запросов и получение ответов]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=100136#p100136</link>
			<description><![CDATA[<div class="quotebox"><blockquote><p>используются необъявленные переменные UInt и PTR (такое чувство, что их забыли взять в кавычки).</p></blockquote></div><p>Да тоже были глюки с этим. Заключаешь в кавычки, и работает. Но при следующем запуске винды, код может работать и без кавычек.</p><div class="quotebox"><blockquote><p>Что касается функции SetTimerF()</p></blockquote></div><p>Тоже не понял, разве не проще использовать &quot;Bind&quot; к объекту функции.</p>]]></description>
			<author><![CDATA[null@example.com (serzh82saratov)]]></author>
			<pubDate>Sun, 03 Jan 2016 16:25:58 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=100136#p100136</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Асинхронная отправка нескольких запросов и получение ответов]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=100135#p100135</link>
			<description><![CDATA[<p>Почему непрерываемый? Как и любой другой, он прерываем между соседними командами.</p>]]></description>
			<author><![CDATA[null@example.com (YMP)]]></author>
			<pubDate>Sun, 03 Jan 2016 15:47:03 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=100135#p100135</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Асинхронная отправка нескольких запросов и получение ответов]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=100132#p100132</link>
			<description><![CDATA[<div class="quotebox"><cite>Malcev пишет:</cite><blockquote><p>А вот от меток, наверное, можно избавиться, там по ссылке упоминается:<br /></p><div class="quotebox"><blockquote><p>With SetTimerF() you could make this even cleaner because you would only need one timer.</p></blockquote></div></blockquote></div><p>В коде из той темы метки заменили функциями (func и func2) - это ничего же не меняет: какая разница, что плодить, если всё равно приходится плодить?<br />Что касается функции SetTimerF() - я её вообще не осилил, там и оформление дурацкое и кажется полно ошибок, т.к. у всех DllCall вызовов там используются необъявленные переменные UInt и PTR (такое чувство, что их забыли взять в кавычки).<br /></p><div class="quotebox"><cite>YMP пишет:</cite><blockquote><p>А для чего необходимы таймеры? Почему просто не опрашивать все объекты по очереди?</p></blockquote></div><p>Для асинхронности же. Как можно опрашивать все объекты по очереди? Только циклом, а цикл - это уже непрерываемый поток.</p>]]></description>
			<author><![CDATA[null@example.com (Drugoy)]]></author>
			<pubDate>Sun, 03 Jan 2016 14:23:34 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=100132#p100132</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Асинхронная отправка нескольких запросов и получение ответов]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=100124#p100124</link>
			<description><![CDATA[<p>А для чего необходимы таймеры? Почему просто не опрашивать все объекты по очереди?</p>]]></description>
			<author><![CDATA[null@example.com (YMP)]]></author>
			<pubDate>Sun, 03 Jan 2016 09:09:33 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=100124#p100124</guid>
		</item>
		<item>
			<title><![CDATA[Re: AHK: Асинхронная отправка нескольких запросов и получение ответов]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=100122#p100122</link>
			<description><![CDATA[<p>Объекты, думаю, для каждого запроса надо создавать новые.<br />А вот от меток, наверное, можно избавиться, там по ссылке упоминается:<br /></p><div class="quotebox"><blockquote><p>With SetTimerF() you could make this even cleaner because you would only need one timer.</p></blockquote></div><p><a href="https://autohotkey.com/board/topic/59492-settimerf-settimer-for-functions/?p=670275">https://autohotkey.com/board/topic/5949 … /?p=670275</a><br />Но у меня не получается:<br /></p><div class="codebox"><pre><code>loop 5
{
   HttpObj%A_Index% := ComObjCreate(&quot;WinHttp.WinHttpRequest.5.1&quot;)
   HttpObj%A_Index%.Open(&quot;GET&quot;,&quot;http://forum.script-coding.com/viewforum.php?id=13&amp;p=&quot; A_Index,true)
   HttpObj%A_Index%.Send()
   SetTimerF(&quot;func&quot;,-1,Object(1, A_Index))
}
loop 5
{
   n := A_Index
   loop
   {
      if (text%n% != &quot;&quot;)
         break 
   }
}
msgbox, done
Return

func(p){
global
HttpObj%p%.WaitForResponse()
text%p% := HttpObj%p%.ResponseText
}


SetTimerF( Function, Period=0, ParmObject=0, Priority=0 ) { 
 Static current,tmrs:=[] ;current will hold timer that is currently running
 If IsFunc( Function ) {
    if IsObject(tmr:=tmrs[Function]) ;destroy timer before creating a new one
       ret := DllCall( &quot;KillTimer&quot;, UInt,0, PTR, tmr.tmr)
       , DllCall(&quot;GlobalFree&quot;, PTR, tmr.CBA)
       , tmrs.Remove(Function) 
    if (Period = 0 || Period = &quot;off&quot;)
       return ret ;Return as we want to turn off timer
	 ; create object that will hold information for timer, it will be passed trough A_EventInfo when Timer is launched
    tmr:=tmrs[Function]:={func:Function,Period:Period=&quot;on&quot; ? 250 : Period,Priority:Priority
								,OneTime:Period&lt;0,params:IsObject(ParmObject)?ParmObject:Object()
								,Tick:A_TickCount}
    tmr.CBA := RegisterCallback(A_ThisFunc,&quot;F&quot;,4,&amp;tmr)
    return !!(tmr.tmr  := DllCall(&quot;SetTimer&quot;, PTR,0, PTR,0, UInt
								, (Period &amp;&amp; Period!=&quot;On&quot;) ? Abs(Period) : (Period := 250)
								, PTR,tmr.CBA,&quot;PTR&quot;)) ;Create Timer and return true if a timer was created
				, tmr.Tick:=A_TickCount
 }
 tmr := Object(A_EventInfo) ;A_Event holds object which contains timer information
 if IsObject(tmr) {
	 DllCall(&quot;KillTimer&quot;, PTR,0, PTR,tmr.tmr) ;deactivate timer so it does not run again while we are processing the function
	 If (current &amp;&amp; tmr.Priority&lt;current.priority) ;Timer with higher priority is already current so return
		 Return (tmr.tmr:=DllCall(&quot;SetTimer&quot;, PTR,0, PTR,0, UInt, 100, PTR,tmr.CBA,&quot;PTR&quot;)) ;call timer again asap
	 current:=tmr
	 ,tmr.tick:=ErrorLevel :=Priority ;update tick to launch function on time
	 ,tmr.func(tmr.params*) ;call function
    if (tmr.OneTime) ;One time timer, deactivate and delete it
       return DllCall(&quot;GlobalFree&quot;, PTR,tmr.CBA)
				 ,tmrs.Remove(tmr.func)
	 tmr.tmr:= DllCall(&quot;SetTimer&quot;, PTR,0, PTR,0, UInt ;reset timer
				,((A_TickCount-tmr.Tick) &gt; tmr.Period) ? 0 : (tmr.Period-(A_TickCount-tmr.Tick)), PTR,tmr.CBA,&quot;PTR&quot;)
	 current= ;reset timer
 }
}</code></pre></div>]]></description>
			<author><![CDATA[null@example.com (Malcev)]]></author>
			<pubDate>Sun, 03 Jan 2016 02:11:01 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=100122#p100122</guid>
		</item>
		<item>
			<title><![CDATA[AHK: Асинхронная отправка нескольких запросов и получение ответов]]></title>
			<link>https://forum.script-coding.com/viewtopic.php?pid=100118#p100118</link>
			<description><![CDATA[<p>Есть <a href="https://github.com/Drugoy/Autohotkey-scripts-.ahk/blob/master/SilentScreenshotter/SilentScreenshotter%28%2Bupload%29.ahk">скрипт</a>, с примерно такой логикой (абстракция):<br />Пользователь отправляет n веб-запросов на веб-сервер (imgur), сервер их какое-то время обрабатывает, а потом отсылает ответы. Текстовые ответы надо поймать и (распарсенные) сохранить в буфер обмена.<br />Хочу, чтоб это делалось асинхронно, т.е. чтобы для отправки второго запроса не требовалось дождаться ответа на первый запрос.</p><p>Помогите разобраться с тем, как лучше запрограммировать такую логику.</p><p>У меня в скрипте с синхронной работой отправка производится так:<br />1. есть массив/объект с запросами для отправки.<br />2. этот объект передаётся аргументом к функции.<br />3. функция сначала один раз создаёт объект, к которому привязывается ComObject(&quot;WinHttp.WinHttpRequest.5.1&quot;)<br />4. затем функция циклически (for key in argObj) перебирает объект в аргументе, каждый раз выполняя:<br /></p><div class="codebox"><pre><code>httpObj.Open(&quot;POST&quot;, url) ; открываем форму для запроса
httpObj.Send(request%k%) ; отправка данных (каждый раз разные) из перебираемого объекта.
clipboard := clipboard . httpObj.ResponseText ; собираем в переменную ответ сервера</code></pre></div><p>5. с последним запросом функция завершает свою работу</p><p>С переходом на асинхронный подход возникли проблемы: нагуглился <a href="http://autohotkey.com/board/topic/113013-how-to-do-logins-using-the-winhttprequest-com/?p=661089">такой</a> пример асинхронной работы.<br />Т.е. после отправки первого запроса выставляется таймер на однократное выполнение метки (label) (которая начинается с HttpObj1.WaitForResponse() и тем самым сначала ждёт ответа от сервера, а дальнейшие команды выполняются только после его получения).<br />Сразу после того, как таймер был выставлен - скрипт продолжает свою работу и переходит к следующему запросу, который аналогичным образом выставляет ещё один таймер на однократное выполнение уже другой метки.</p><p>Такое решение мне подходит, т.к. получается, что если надо выполнить очередь из 20 асинхронных запросов к серверу и потом собрать 20 ответов на них, то нам надо создавать 20 отдельных объектов, 20 меток (и потом ещё как-то скоординировать их дальнейшую работу, ведь по условием задачи - нам надо всё записать в одну переменную и её содержимое запихнуть в clipboard, а ещё ведь может захотеться и пользователю как-то сообщать о прогрессе выполнения задачи).<br />Мне не хочется плодить метки (т.к. подразумевается, что запросов может быть аж до 255шт) и не хотелось бы плодить объекты без необходимости (т.е. если это необходимо - то ладно).<br />Как же правильно решить такую проблему?</p><p>И т.к. я до этого ни разу не работал с асинхронностью, то сразу сопутствующий вопрос: есть какие-то писанные/неписанные стандарты о том, какой должна быть пауза между запросами и какая скорость запросов обычно считается приемлемой? или это всё сильно зависит от сервера и лучше узнать опытным путём?</p>]]></description>
			<author><![CDATA[null@example.com (Drugoy)]]></author>
			<pubDate>Sat, 02 Jan 2016 15:49:20 +0000</pubDate>
			<guid>https://forum.script-coding.com/viewtopic.php?pid=100118#p100118</guid>
		</item>
	</channel>
</rss>
