Funcion Sleep. Alguna alternativa ¿?

346 views
Skip to first unread message

Rafa Pabd

unread,
Apr 2, 2023, 12:10:34 PM4/2/23
to Harbour Users
Hola, en esta funcion no entiendo la utilidad del bucle do while seconds > 100
FUNCTION FT_SLEEP( nSeconds, nInitial ) 
 IF nInitial == NIL .OR. VALTYPE( nInitial ) != "N"     nInitial := SECONDS()  ENDIF 
 // correct for running at midnight  IF nInitial + nSeconds > 86399     nInitial -= 86399     * Wait until midnight     DO WHILE SECONDS() > 100 // no problem with a _very_ slow machine     ENDDO  ENDIF // calculate final time  nSeconds += ninitial 
 // Loop until we are done  DO WHILE ( SECONDS() < nSeconds )  ENDDO 
 RETURN NIL



Quique

unread,
Apr 4, 2023, 6:32:03 PM4/4/23
to Harbour Users

El bucle es usado para garantizar que no haya error al finalizar el día, tal vez pudieras quitarlo, pero habría que garantizar que no se pierda al momento de la media noche. ¿Alternativa? puedes crear tu propio bucle y contar los segundos con second() o time(), realmente solo hay que dejar que pase el tiempo. Inclusive, podrías utilizar un bloque en el que incluyas inkey( segundos ), pero tendrías que poner una validación para cuando el usuario presione una tecla no termine el bucle.

Lailton Fernando Mariano

unread,
Apr 4, 2023, 7:20:23 PM4/4/23
to Harbour Users
hb_idleSleep( 1.0 ) // one sec

Rafa Pabd

unread,
Apr 5, 2023, 1:59:21 AM4/5/23
to Harbour Users
Hola,

Lo que veo mal de ese bucle es que puede producir una espera innecesaria de ¡ 100 segundos ! si por ejemplo la espera es de 2 segundos cuando la hora es 23:59:59
Ademas no sé como se comporta en un bucle de 100 segundos sin proveer un estado idle al programa.

Salu2

Rafa Pabd

unread,
Apr 5, 2023, 1:59:23 AM4/5/23
to Harbour Users
Hola,

Realmente utilizo el codigo de FT_Sleep() para poner un codeblock en modo espera, de manera que el final del tiempo o bien la ejecucion del codeblock que devuelve un valor booleano determinan la salida del bucle.
Por eso mi interes en esa funcion o cualquiera que posibilite pasar como parametro un codeblock que ejecute una accion y devuelva un valor logico

Saludos

Ash

unread,
Apr 5, 2023, 7:50:24 AM4/5/23
to Harbour Users
SecondsSleep( <nSeconds> ) --> NIL

Regards,
Ash

pete....@gmail.com

unread,
Apr 5, 2023, 8:58:59 AM4/5/23
to Harbour Users
On Wednesday, 5 April 2023 at 14:50:24 UTC+3 Ash wrote:
SecondsSleep( <nSeconds> ) --> NIL


Just for the record: ;-)
this  `SecondsSleep( <nSeconds> )` function,
is always "translated" internally by compiler to
Harbour core function `hb_idleSleep()
That said, I 'd suggest to OP (trepao) to consider using
the relevant Harbour core functions  hb_idle**().
A brief description can be found here!
And extended documentation here!

regards,
Pete

Rafa Pabd

unread,
Apr 5, 2023, 1:35:16 PM4/5/23
to Harbour Users
Hello, I don't need anything related to idle times, but what I need is to execute a function, retrying until it returns true or the time is up. That is, I need to be able to retry calling a codeblock but with a timeout.
See above example please: FUNCTION FT_SLEEP( nSeconds, nInitial, bAction ) 
 IF nInitial == NIL .OR. VALTYPE( nInitial ) != "N"     nInitial := SECONDS()  ENDIF 
 // correct for running at midnight  IF nInitial + nSeconds > 86399     nInitial -= 86399     * Wait until midnight     DO WHILE SECONDS() > 100 // no problem with a _very_ slow machine     ENDDO  ENDIF // calculate final time  nSeconds += ninitial 
 // Loop until we are done  DO WHILE ( SECONDS() < nSeconds )     IF bAction != NIL .AND. Eval(bAction)       EXIT    ENDIF   ENDDO 
 RETURN NIL
thanks in any case

Ash

unread,
Apr 5, 2023, 6:46:36 PM4/5/23
to Harbour Users
>A brief description can be found here!
This is your website, not many folk might be aware of it. 

>And extended documentation here!
This I agree is an official Harbour Reference Guide but I can't find a description of hb_IdleSleep() there.

Regards,
Ash

pete....@gmail.com

unread,
Apr 6, 2023, 2:05:47 AM4/6/23
to Harbour Users
Hello Ash

On Thursday, 6 April 2023 at 01:46:36 UTC+3 Ash wrote:
>A brief description can be found here!
This is your website, not many folk might be aware of it. 
Well, any advertisement sponsors welcome! :-)
(In fact, I do not consider it being "my website", since it's a wiki open to everybody
who wish to add a chunk (or more) of documentation.)
 
>And extended documentation here!
This I agree is an official Harbour Reference Guide but I can't find a description of hb_IdleSleep() there.
Yes, you're right! 
Obviously, the official Harbour doc site needs more attention (housekeeping, improvement, etc),
which due to lack of availability by people willing/able to maintain it, is not currently possible I'm afraid.
(In the past it was feasible to edit the content of pages, unfortunately, last time I tried to do it didn't succeed.)
Anybody who thinks could contribute and has an interest and ability to involve,  here is the chance, I think.

regards,
Pete

Ash

unread,
Apr 7, 2023, 7:53:09 AM4/7/23
to Harbour Users
Hello Pete,

 If I continue, I'll be hijacking this conversation. The best I could do is to share my knowledge, right here.

Regards,
Ash 

Rafa Pabd

unread,
Apr 18, 2023, 1:05:06 PM4/18/23
to Harbour Users
Despues de corregir repetidas veces a la IA, me devuelve este codigo que en principio doy por bueno. 
Tiene la caracteristica que sobrepasa el efecto medianoche de infinitos dias y no solo de uno

Algún hint ?


FUNCTION hb_dateSeconds()
   LOCAL dUnixEpoch := CTOD( "01/01/1970" ), nDays, nSeconds

   // Calcular la diferencia en días entre la fecha actual y la época Unix
   nDays := DATE() - dUnixEpoch

   // Convertir la diferencia en días a segundos y sumar la cantidad de segundos transcurridos en el día actual
   nSeconds := nDays * 86400 + VAL( SUBSTR( TIME(), 1, 2 ) ) * 3600 + VAL( SUBSTR( TIME(), 4, 2 ) ) * 60 + VAL( SUBSTR( TIME(), 7, 2 ) )

   RETURN nSeconds


FUNCTION WaitOrCodeblockTrue( nSeconds, bCodeblock )
   LOCAL nStartSeconds, nCurrentSeconds, nWaitedSeconds

   nStartSeconds := hb_dateSeconds()
   nWaitedSeconds := 0

   DO WHILE nWaitedSeconds < nSeconds .AND. !Eval( bCodeblock )
      nCurrentSeconds := hb_dateSeconds()
      nWaitedSeconds := nCurrentSeconds - nStartSeconds

      hb_idleSleep( 0.1 ) // Espera 100 ms para reducir la carga de la CPU
   ENDDO

   RETURN NIL

Rafa Pabd

unread,
Apr 18, 2023, 1:14:30 PM4/18/23
to Harbour Users
Le veo el "inconveniente" que la funcion sólo funciona con segundos y no fracciones de tiempo inferiores. Habria que mejorarla en ese sentido

CV

unread,
Apr 18, 2023, 8:22:34 PM4/18/23
to Harbour Users
Rafa

Para ser completamente funcional la función TIME() debería ser invocada sólo una vez y su valor almacenado en una variable.
Podría suceder que cambie su valor entre 3 invocaciones sucesivas.

Creo que si usas SECONDS() en vez de TIME() seria igualmente funcional (sin cálculos adicionales), dado que se utiliza DATE() para tener en cuenta la fecha del día.
Con seconds() se tendrían en cuenta fracciones de segundo, pero los intervalos de cambio de esta función siempre son mayores a 0.01 segundo, lo que lo hace poco precisa.
Prueba esto para entender lo que indico:
function main()
local wSegs
while .T.
       wSegs := seconds()
       while wSegs = seconds() ; enddo
       ? wSegs, seconds()
enddo
return nil

Suerte y saludos!
--
Claudio Voskian
Buenos Aires - Argentina

Rafa Pabd

unread,
Apr 19, 2023, 5:16:41 AM4/19/23
to Harbour Users
Claudio,

¿ Qué le parece esto ? Ahora si permitiria hasta centesimas de segundo, que es lo que devuelve Seconds()
Este codigo es mucho mas claro que el anterior. A la IA no se le ocurrió jajajajajajajaja

FUNCTION hb_dateSeconds()
   LOCAL dUnixEpoch := CTOD( "01/01/1970" ), nDays, nSeconds


   // Calcular la diferencia en días entre la fecha actual y la época Unix
   nDays := DATE() - dUnixEpoch

   // Convertir la diferencia en días a segundos y sumar la cantidad de segundos transcurridos en el día actual
    nSeconds := nDays * 86400+ Seconds()

   RETURN nSeconds

Rafa Pabd

unread,
Apr 19, 2023, 7:09:10 AM4/19/23
to Harbour Users

Quiza quedaria mejor parametrizando la espera de hb_idleSleep()  o calculandola en funcion de la parte decimal de los segundos a esperar (nSeconds), pero de momento, asi quedaria:

#Define dBASE_                      CToD("01/01/1980")
#Define nTRANSCURRIDO_  (Date()- dBASE_)* 86400+ Seconds()

// nSeconds puede ser un entero o llevar hasta dos decimales
// bCodeblock es opcional y devolvera .T. para terminar la espera
FUNCTION SleepOrTrue( nSeconds, bCodeblock )
   LOCAL nStartSeconds, nCurrentSeconds, nWaitedSeconds
   
   nStartSeconds := nTRANSCURRIDO_
   nWaitedSeconds := 0

   DO WHILE nWaitedSeconds < nSeconds .AND. If(bCodeBlock == NIL, .T., !Eval( bCodeblock ))
      nCurrentSeconds := nTRANSCURRIDO_

      nWaitedSeconds := nCurrentSeconds - nStartSeconds

      hb_idleSleep( 0.1 ) // Espera 100 ms para reducir la carga de la CPU
      
   ENDDO

   RETURN NIL

Reply all
Reply to author
Forward
0 new messages