Duda con bucles y timers

Tus preguntas. Algoritmos o Grupos de Comandos formando Programas Escripts.
Responder
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Duda con bucles y timers

Mensaje por Jonny »

Hola,

Tengo la duda (quizá es normal que ocurra) de porqué, al desarrollar una aplicación simulando multihilo, cuando en uno de estos (un timer en realidad) hay un bucle "While 1" por ejemplo, que procesa algoritmos muy complejos, que maneja gran cantidad de información o simplemente el bucle no termina nunca (Por ejemplo: while 1 ... wend), los demás timers (Hilos) se quedan colgados osea, se cuelga la aplicación (no responde ningún hilo, como si se hubiera desarrollado el programa de forma secuencial) no se si me explico.

Si esto es normal ¿Porqué hacer aplicaciones multihilo?, que como he leído en barios foros dedicados a la programación es mucho mejor ¿Porqué es mejor si el estado de un hilo afecta a otro, y como dije el resultado es como si la aplicación fuera procedimental?...

Y ahora la gran pregunta:
¿Puede hacerse algo (con autoit) para que esto no ocurra?, de forma que si un timer tiene un bucle que tarda mucho en ejecutarse el resto del programa siga funcionando con normalidad.

Gracias a quien tenga una respuesta, porque el programa que estoy haciendo cada vez se complica más...

salu2!
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Duda con bucles y timers

Mensaje por Chefito »

Una pregunta....para que quieres meter un while 1....wend en un timer???? :smt017 . Razona....vas a volver loco al ordenador :smt018 . Piensa que el timer practicamente se debe hacer para sustituir bucles de estos.
Si metes un while 1....wend dentro de un timer, este bucle puede que se ejecute infinitamente y no salga, o quien sabe que cosas....además, se ejecutará a más velocidad que el timer, liando mucho más la cosa. Consecuencias que pueden ocurrir con esto: cosas imprevisibles, cuelges, etc.

Lo dicho....ten cuidado con estas prácticas. Un timer sustituye a un while, ya que el timer ejecuta el código a mucha velocidad indefinidamente.

Otra cosa.....bueno, viendo que te interesa mucho el tema, te voy a dar donde buscar.....pero solo eso. Yo paso de meterme en temas de apis multiThread (multihilo). Las apis multihilo que te pueden interesar son:
CreateThread, EnumThreadWindows, ExitThread, GetCurrentThread, GetCurrentThreadId, GetExitCodeThread, GetGUIThreadInfo, GetMessageExtraInfo, GetThreadPriority, GetThreadTimes, SetThreadPriority, SwitchToThread, TerminateThread.


Otras que te pueden interesar para prácticas de estas son las que crean ganchos (hook):
SetWindowsHookEx, SetWindowsHookEx, UnhookWindowsHookEx.

Otra muy interesante: CallWindowProc

Y por supuesto las de tiempo: KillTimer, SetTimer, timeKillEvent, timeSetEvent.....entre otras.

Seguro que hay muchas más y mejores, pero vete a saber :smt017 .

Muchas de estas funciones son interesantes porque pasaban procedimientos a otro procedimiento (en vb era con addressof).
Que te lo explique microsoft, porque como te lo tenga que decir yo vamos listos :smt021 .
http://msdn.microsoft.com/es-es/library ... S.80).aspx

Si te metes en todo esto....sobretodo en multihilo.....ya puedes empezar a volverte loco :smt005 .
Busca estas funciones por el foro ingles, puede que tengas suerte y hayan programas realizados con estas apis.

Yo no te voy a poder ayudar mucho, ya que este tema, aunque parezca mentira, me supera y no tengo ganas de pelearme con esto.

Saludos :smt021 .
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Duda con bucles y timers

Mensaje por Jonny »

Hola

sí, sí... Es cierto todo lo que dices y era consciente de ello. La cosa, es que estoy desarrollando un servidor bastante complejo, que ha de realizar barias tareas.
Por ejemplo, atender peticiones de clientes, para validar programas, enviar e-mails, sms etc, pero a su vez actuar como cliente, consultando el correo electrónico de un servidor pop3 y demás servicios. La idea de hacer cada servicio (por así decirlo) en aplicaciones separadas no me convence, pues quiero tener una única aplicación que haga todo esto y que además incluya una interface con la que poder gestionar el programa (ver historiales monitorizar eventos en tiempo real)... etc etc...

¿Porqué poner un while en un timer?
puse el ejemplo de while ... wend, (sin sentido alguno) para explicar más o menos a lo que me refería, en ningún momento necesito hacer algo así :P.
Pero por ejemplo la parte encargada de esperar datos de una conexión entrante al programa (cliente) sí ha de tener un while ¿Verdad?...
Es cierto que si se programa con cuidado este funcionará, si se rompe cuando es debido etc... pero si el cliente en cuestión envía una gran cantidad de datos como también puse a modo de ejemplo el bucle debe ejecutarse ... Por tanto ahí es donde la aplicación se queda como en sleep hasta que dicho bucle termina.

En otro post del foro también en "Soporte" he preguntado como recibir correctamente correos electrónicos de un servidor pop3... Tras unos cuantos problemillas parece funcionar, pero tarda bastante en recibirse el e-mail sobre todo si este tiene datos adjuntos. Este es otro ejemplo de que la aplicación se cuelga mientras esa tarea se está realizando y precisamente quise desarrollar el software simulando el multihilo, porque creí que no ocurriría esto...
¿Podría sustituir los whiles que contienen los timers y que procesan mucha información por timers?...
es una solución que se me ocurrió.

Porque de aplicar las apis que me comentas imagino que sería el mismo el problema ¿no?
aunque veo que las apis de timers no son las mismas que las de los hilos, quizá no tendría este problema de utilizarlas... buf, que escalofríos pensar en las apis...

Buscaré de todos modos algo en el foro en ingles sobre todas las que me pusiste, haber si hay suerte... yo tenía un código que posteé por aquí que creaba hilos mediante las apis, pero faltaba pausarlos, detenerlos etc... quizá con lo que me has dicho encuentre algo más, pues no tenía ni idea de como buscar....

Salu2!
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Duda con bucles y timers

Mensaje por Chefito »

Bueno......vamos a ver como lo podemos solucionar. Piensa que un timer no se para. O sea, que va ha ser llamado continuamente. Que problema va a haber con esto? Pues que puede que se solapen dos llamadas o más a una función a causa del timer. Como podríamos solucionarlo? Pues con una simple condición, pasandole a una variable que si no ha acabado de hacer lo que tenga que hacer (en tu caso coger unos datos) no entre en el código del procedimiento. Cuando acabe de coger estos datos, pondríamos la variable de la condición a true y ya se podría entrar de nuevo. Y en tal que entrase, pues que pusiese esa variable a false. Así continuamente. No se si lo has entendido :smt016 .

A lo mejor te interesa saber que existe un control muy extendido y muy muy muy documentado para manejo de conexiones. Este control se llama winsock (busca códigos en la red y en el foro ingles. Yo he visto muchos). Es muy facil de manejar y tiene funciones eventos (como si fuesen multihilo) para realizar muchas cosas....como coger datos continuamente sin perjudicar el resto del código. Se puede hacer todo tipo de conexiones. Yo he hecho conexiones a servidores de correo, ftp, irc, etc etc.
Mira esto que puede que te guste :smt002 .

Saludos :smt004 .
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Duda con bucles y timers

Mensaje por Jonny »

Hola

sí, lo entendí... buena solución...

En realidad, así como para probar lo que voy haciendo en las funciones de gestión de correo, en el timer qe las maneja puse un _timer_killtimer() para que únicamnete se ejecutara una vez todo el código (no quiero imaginar si tubiera que ejecutarse constantemente jejejeje) de todas formas, se me ocurrió o bien llamar al timer cada x tiempo 1 minuto por ejemplo, o pararlo cada vez que se le llame antes de ejecutar ningún procedimiento y una vez ejecutados todos volver a llamar al timer. De esta forma, en teoría se ejecutará constantemente, pero sin solaparse las llamadas a funciones ¿verdad?... al ser un timer para comprobar si hay correo en un servidor no es necesario que el timer se ejecute constantemente como si fuera una función para esperar conexiones entrantes...

¿Winsock? ¿Me lo parece, o suena a api? ejejejejej

Yo eso lo había visto, pero en algún manual de C y C++... Pensé que era la forma de trabajar sockets de ese lenguaje.

Le hecharé un vistazo a ver que encuentro.
Gracias,

Salu2!
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Duda con bucles y timers

Mensaje por Chefito »

Sí....también lo pensé, el ir matando el timer y creandolo continuamente, pero eso creo que es mucho más pesado para ejecutar que una simple comparación.
El método que te dije era para timers con intervalos muy pequeños (conseguir datos continuamente, etc). Pero para cosas como comprobar la bandeja de entrada.....eso se puede hacer con un simple timer que tenga un intervalo mucho más grande (por ejemplo unos sg.). Incluso para ver las conexiones, tampoco se necesita velocidades muy muy excesivas.

WinSock....apis.....pues sí, las apis siempre han estado relacionadas con esta palabra :). Pero microsoft tiene un control (windows) que se llama así (creo que el nombre completo era mswinsck.ocx). Y te aseguro que es mucho más facil y cómodo de programar, con diferencia.

Saludos :smt031 .
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Duda con bucles y timers

Mensaje por Jonny »

Hola

a ver a quien se le ocurre, como hecharme un cable con esto ... que está resultando un tanto complicado.

Viendo que por mí mismo no hay forma de hacer un código que descargue mensajes muy pesados del servidor pop3 sin sorpresas (cuelgues del programa y demás) he optado por como dige, utilizar parte de la librería pop3 que descargué del foro inglés y adjunté en otro post.

La cosa, como ya comenté, es que las funciones que utiliza (3) se basan en bucles, nada compatible con mi aplicación que se basa en timers para simular hilos (no estoy preparado para hacer hilos de verdad con apis), por lo que el programa queda un tanto ... pésimo, pues si mi intención es comprobar constantemente la bandeja de entrada el resto de funciones del programa no van a funcionar practicamente nunca.

así pues, pongo el código que tengo actualmente para recoger los e-mails a ver si alguien me ayuda a hacer lo mismo pero en un timer... Esque, con tanta función y tanto bucle, por más bueltas que le doy no se como meter todo esto en una única función que actúe como timer...

Adelanto, que a este timer se le llamaría desde otro timer, lo que sería el hilo que gestiona el correo electrónico, pues hay más funciones vinculadas a estas como la encargada de establecer la conexión y el login con el servidor, la que comprueba si hay e-mails en éste (para llamar a estas funciones).... etc etc.

ahí va el código:

Código: Seleccionar todo


Global Const $Pop3_Error_Server_Response_Timeout=2
Global Const $Pop3_Ok="^\+OK"
Global Const $Pop3_Error_No_Ok_Response=9
Global Const $Pop3_Error_TcpRecv_Timeout=6
Global Const $Pop3_Error_No_Auth=5
Global $Pop3_Server_Response_Timeout=60000

Func ListMail_Get($NumMails)
Local $Ret, $ARet[1]
For $I=1 To $NumMails Step +1
TcpSend($ClientSocket[0], "retr "&$I&" all"&@CRLF)
$Ret=_Pop3WaitForOk()
If @Error Then
TcpCloseSocket($ClientSocket[0])
$ClientSocket[0]=""
ContinueLoop
EndIf
$Ret=_WaitTcpResponse()
If @Error Then
TcpCloseSocket($ClientSocket[0])
$ClientSocket[0]=""
ContinueLoop
EndIf
While Not StringRegExp($Ret, "\r\n\.\r\n")
$Ret=$Ret&_WaitTcpResponse()
If @Error Then
TcpCloseSocket($ClientSocket[0])
$ClientSocket[0]=""
ContinueLoop
EndIf
Wend
ReDim $ARet[UBound($ARet, 1)+1]
$ARet[UBound($ARet, 1)-1]=$Ret
Next
$ARet[0]=UBound($ARet, 1)-1
Return $ARet
EndFunc
Func _Pop3WaitForOk()
Local $Ret
Local $T=TimerInit()
While 1
If TimerDiff($T)>$Pop3_Server_Response_Timeout Then
SetError($Pop3_Error_Server_Response_Timeout)
Return -1
EndIf
$Ret=_WaitTcpResponse()
If Not @Error And StringRegExp($Ret, $Pop3_Ok) Then
Return $Ret
EndIf
Wend
SetError($Pop3_Error_No_Ok_Response)
Return -1
EndFunc
Func _WaitTcpResponse($Timeout=30000)
Local $Ret
Local $T=TimerInit()
While 1
If TimerDiff($T)>$Timeout Then
SetError($Pop3_Error_TcpRecv_Timeout)
Return -1
EndIf
$Ret=TCPRecv($ClientSocket[0], 50000)
If $Ret<>"" Then
Return $Ret
EndIf
Wend
EndFunc

Gracias por adelantado,

Salu2!
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Duda con bucles y timers

Mensaje por Chefito »

Es que has quitado o cambiado la clave del correo [email protected]? He querido variar un poco las funciones para ver si lograba cortar los mensajes antes de que cargase los datos adjuntos y me da fallo.

Tu último código es un trozo que no va. Intenta poner códigos funcionales.

Si me habilitas de nuevo la cuenta de correo (la anterior), intentaré darte un ejemplo de como cortarlo.

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Jonny
Profesional del Autoit
Mensajes: 1042
Registrado: 30 Jun 2008, 20:08

Re: Duda con bucles y timers

Mensaje por Jonny »

Hola

Resulta que la cuenta de correo no es mía...

Puedo acceder a ella mientras programo todo esto, pero luego no tendré acceso... En cualquier caso, ya está la misma contraseña.

¿mi último código no es funcional?
¿A que te refieres exactamente?...

creo que comenté que no entendía muy bien el código, (respecto al protocolo que sigue) y al ver que funciona me limité a ponerlo...
¿Será en forma de timer el que intentes darme?
Gracias,

Salu2!
Responder