In order for this site to work correctly we need to store a small file (called a cookie) on your computer. Most every site in the world does this, however since the 25th of May 2011, by law we have to get your permission first. Please abandon the forum if you disagree.

Para que este foro funcione correctamente es necesario guardar un pequeño fichero (llamado cookie) en su ordenador. La mayoría de los sitios de Internet lo hacen, no obstante desde el 25 de Marzo de 2011 y por ley, necesitamos de su permiso con antelación. Abandone este foro si no está conforme.

Trabajado con Future's

Foro de Xailer profesional en español
User avatar
bingen
Posts: 439
Joined: Mon Jul 07, 2014 8:17 pm
Location: Bilbao
Contact:

Trabajado con Future's

Postby bingen » Mon Apr 20, 2020 4:24 pm

Buenas Xailer Team, estoy probando ya los nuevos Futures de la beta de Xailer 7 y dada la lógica falta de documentación, me encuentro con algunas dudas y problemas.

Pienso sustituir todos mis hilos por Futures para ganar en simplicidad de código y control pero....

1.- Si los futures se apilan para ser ejecutados en otro hilo de forma secuencial, como puedo saber
a) Si han finalizado todos, por que si intento salir de la aplicación antes de acabar estos, la aplicación da un lógico error
b) Se puede saber la lista de los que quedan por ejecutar? Se podrá asignar un nombre a cada uno para saber cual está haciendo y cuales quedan? He modificado el Sample Futures.Prg y cada Future me devuelve un :TaskCount() de 1, quizás deberia de instanciar para ello un solo Appdata:Future por aplicación y cargar a el todos los futures.

2.- Si hago un AWAIT INLINE {||SYNCHRO FUNCTION ¿se puede establecer un OnComplete? o no hay manera salvo haciendo un objeto instanciado con nombre como oFuture := TFuture():New()

3.- Además de OnComplete y OnError no veo otros eventos. No sería útil un evento OnStart por ejemplo, justo al contrario que OnComplete para inicializar objetos por ejemplo? No es necesario por que se puede hacer antes de llamar al Future pero...

4.- Si da un error la aplicación mientras está ejecutando un Future sale el error en pantalla pero se bloquea todo, lo he probado con el Sample Futures.Prg poniendo un error al final del tercero y poniendo en marcha los otros 2 pongo en marcha el tercero y zasca.

5.- Por último un error, he creado un Future para realizar las copias de seguridda de las BBDD de la aplicación al entrar (antes lo hacia con tThread) y ok funciona bien, es un proceso pesado y entre tanto puedo hacer otras cosas, esa es la idea. Pero resulta que tengo varios timer que refrescan diferentes cosas y si saltan algunos de ellos provocan errores curiosos, este es el primero y ando detras de otro que no se produce siempre.

______________________ Información detallada del error ______________________

Subsistema: WINOLE
Código de error: 1007
Estado: .F.
Descripción: No se puede hacer una llamada de salida desde la aplicación que está ejecutando una llamada sincrónica de entrada. (0x8001010D)
Operación: CONNECTSERVER
Argumentos:
Fichero: SWbemLocator
Código error SO: -2147352567

Pila de llamadas:
REALMEMORY (1436)
WIDGETSYSMETERREFRESH (1046)
(b)TFRMMAIN_FORMINITIALIZE (125)
TTIMER:ONTIMER (0)
(b)XTIMER (43)
TTIMER:WMTIMER (0)
WIN_OLEAUTO:RUN (0)
TSQLSTRUCTURE:DAILYBACKUP (3151)
(b)TFRMMAIN_PRUEBAASYNC (1600)
TFUTURE:RUNSYNCHRO (244)
(b)XFUTURE (51)
TFUTURE:WMXAILER (0)
RUNFORM (0)
TAPPLICATION:RUN (289)
MAIN (16)

Esta es la función que ejecuta, aunque me pasa en otras también, parace que no se puede acceder al API de Windows mientras está el future en marcha.

//Escanea la memoria del equipo y devuelve sus características en un array de 1 línea
//Devuelve tamaño_mem_real, tamaño_libre_mem_real, tamaño_mem_virtual, tamaño_libre_mem_virtual
Function RealMemory()

LOCAL oScriptObj, oWmiService, aRM := {}, oRM, aInfo:={}

oScriptObj = CREATEOBJECT( "wbemScripting.SwbemLocator" )
oWmiService = oScriptObj:ConnectServer() <<======Aqui se produce el error ¿?¿?¿?¿?¿??¿

aRM = oWmiService:ExecQuery("Select * from Win32_OperatingSystem")

for each oRM in aRM
AAdd(aInfo,{Val(oRM:TotalVisibleMemorySize),Val(oRM:FreePhysicalMemory) ,Val(oRM:TotalVirtualMemorySize),Val(oRM:FreeVirtualMemory)})
next

RETURN aInfo

Muchas gracias.
BiSoft Desarrollo de software profesional
http://www.bisoft.es
User avatar
ignacio
Site Admin
Posts: 8681
Joined: Mon Apr 06, 2015 8:00 pm
Location: Madrid, Spain
Contact:

Re: Trabajado con Future's

Postby ignacio » Mon Apr 20, 2020 5:01 pm

hola,

1.- Si los futures se apilan para ser ejecutados en otro hilo de forma secuencial, como puedo saber
a) Si han finalizado todos, por que si intento salir de la aplicación antes de acabar estos, la aplicación da un lógico error


Tienes el evento OnComplete y OnError en el futuro. Siempre puedes parar todo con el método TFuture:Stop()

b) Se puede saber la lista de los que quedan por ejecutar? Se podrá asignar un nombre a cada uno para saber cual está haciendo y cuales quedan? He modificado el Sample Futures.Prg y cada Future me devuelve un :TaskCount() de 1, quizás deberia de instanciar para ello un solo Appdata:Future por aplicación y cargar a el todos los futures.


He añadido el método CurrentTask(). Cada futuro puede tener múltiples tareas (tasks) pero se ejecutan una detrás de otra y no todas a la vez.

Además siempre se puede acceder a los 'taks' de un TFuture ya que es una instancia de la clase TFutureTask. Dejo el prototipado:

Code: Select all

CLASS TFutureTask

PUBLIC:
   PROPERTY oParent     AS TFuture
   PROPERTY oError      READONLY
   PROPERTY nState      READONLY INIT ftUNCOMPLETED //      ftUNCOMPLETED        =>  0, ftCOMPLETEDWITHVALUE =>  1,  ftCOMPLETEDWITHERROR =>  2

   PROPERTY ReturnValue READONLY

   EVENT OnComplete( oSender, ReturnValue )

PUBLIC:
   METHOD New( oFuture, bBlock ) CONSTRUCTOR
   METHOD End()
   METHOD Run()

END CLASS


Por lo tanto sólo tienes que comprobar la propiedad nState de TFuture:aThreadTasks[..]

Code: Select all

2.- Si hago un AWAIT INLINE {||SYNCHRO FUNCTION ¿se puede establecer un OnComplete? o no hay manera salvo haciendo un objeto instanciado con nombre como oFuture := TFuture():New()


Puedes usar la variable LOCAL 'ThisFuture', que siempre existe cuando pones la clásula ASYNC

4.- Si da un error la aplicación mientras está ejecutando un Future sale el error en pantalla pero se bloquea todo, lo he probado con el Sample Futures.Prg poniendo un error al final del tercero y poniendo en marcha los otros 2 pongo en marcha el tercero y zasca.


El primer código del ejemplo, en el método Btn1Click te muestra claramente cómo protegerte de los errores. Simplemente has de descomentar la línea que captura el error:

Code: Select all

ThisFuture:OnError := {|| .T. } // Do not stop


Y la línea que lo provoca en el bucle:

Code: Select all

nFor := nFor + "a"


Code: Select all

5.- Por último un error, he creado un Future para realizar las copias de seguridda de las BBDD de la aplicación al entrar (antes lo hacia con tThread) y ok funciona bien, es un proceso pesado y entre tanto puedo hacer otras cosas, esa es la idea. Pero resulta que tengo varios timer que refrescan diferentes cosas y si saltan algunos de ellos provocan errores curiosos, este es el primero y ando detras de otro que no se produce siempre.


Esto tiene que quedar muy claro. Desde el futuro NO SE PUEDE ACCEDER AL INTERFACE DE USUARIO, y los TIMERS por supuesto tampoco. La solución es bien fácil, crea el timer en el Hilo principal.

Un saludo
Ignacio Ortiz de Zúñiga
[Equipo de Xailer / Xailer team]
http://www.xailer.com
User avatar
bingen
Posts: 439
Joined: Mon Jul 07, 2014 8:17 pm
Location: Bilbao
Contact:

Re: Trabajado con Future's

Postby bingen » Tue Apr 21, 2020 5:17 pm

>>Esto tiene que quedar muy claro. Desde el futuro NO SE PUEDE ACCEDER AL INTERFACE DE USUARIO, y los TIMERS por supuesto tampoco. La solución es bien fácil, crea el timer en el Hilo principal.

Hola Ignacio, creo que no me expliqué bien. El timer está en el hilo principal, ya se que no puedo hacerlo desde el hilo, de hecho está funcionando con los tThread pero no con los Futures
BiSoft Desarrollo de software profesional
http://www.bisoft.es
User avatar
ignacio
Site Admin
Posts: 8681
Joined: Mon Apr 06, 2015 8:00 pm
Location: Madrid, Spain
Contact:

Re: Trabajado con Future's

Postby ignacio » Tue Apr 21, 2020 8:44 pm

Buenas,

Acabo de añadir en el ejemplo de futuros un nuevo control que incluirá Xailer 7 que incorpora un timer y no observo ningún problema. De hecho, el comportamiento de TFuture con los hilos es absolutamente transparente y sencillo que se resume en una sola línea de código:

hb_ThreadStart( nFlags, bCode )

No obstante, si consigues reproducirlo con el ejemplo de los Tfuture, te ruego me digas como. Gracias.

Un saludo

Ignacio Ortiz de Zúñiga
[Equipo de Xailer / Xailer team]
http://www.xailer.com
User avatar
bingen
Posts: 439
Joined: Mon Jul 07, 2014 8:17 pm
Location: Bilbao
Contact:

Re: Trabajado con Future's

Postby bingen » Tue Apr 28, 2020 6:20 pm

Ok a ver si puedo reproducirlo, el timer llama al API de windows para preguntarle datos del sistema como la memoria y el procesador ocupados/disponibles
BiSoft Desarrollo de software profesional
http://www.bisoft.es

Return to “Spanish”