Spanish [ENTENDIDO] Wait For

edgar_ortiz

Active Member
Licensed User
Longtime User
Estimad@s,

Revisando el tutorial:
https://www.b4x.com/android/forum/threads/b4x-okhttputils2-with-wait-for.79345/

Ahora definitivamente ya estoy mas confundido... NO entiendo la diferencia entre

"Descargando dos recursos, uno tras otro:"
B4X:
Sub DownloadTwoLinks
   Dim j As HttpJob
   j.Initialize("", Me) 'name is empty as it is no longer needed
   j.Download("https://www.google.com")
   Wait For (j) JobDone(j As HttpJob)
   If j.Success Then
     Log(j.GetString)
   End If
   j.Release
   'second request
   Dim j As HttpJob 'redim and initialize
   j.Initialize("", Me)
   j.Download("https://www.duckduckgo.com")
   Wait For (j) JobDone(j As HttpJob)
   If j.Success Then
     Log(j.GetString)
   End If
   j.Release
End Sub
y
"¿Cómo descargar una lista de recursos, uno por uno?"
B4X:
Sub Activity_Create(FirstTime As Boolean)
   DownloadMany(Array("http://www.google.com", "http://duckduckgo.com", "http://bing.com"))
End Sub

Sub DownloadMany (links As List)
   For Each link As String In links
     Dim j As HttpJob
     j.Initialize("", Me) 'name is empty as it is no longer needed
     j.Download(link)
     Wait For (j) JobDone(j As HttpJob)
     If j.Success Then
       Log("Current link: " & link)
       Log(j.GetString)
     End If
     j.Release
   Next
End Sub

Al final mi punto es tratar de entender cómo implementar un proceso "sincrónico", por ejemplo necesito cargar a la base de datos del teléfono, los "países", los "departamento de cada país" y los "municipios de cada departamento de cada país", entonces para respetar la integridad de la información, primero debo cargar los países, cuando estos ya estén cargados en la base de datos, ya puedo cargar los departamentos de cada país y cuando los departamentos de cada país ya estén cargados, ya puedo cargar los municipios de cada departamento de cada país.

Agradeciendo de antemano su tiempo,

Saludos,

Edgar
 

TILogistic

Expert
Licensed User
Longtime User
Aqui te explica mejor el Wait For.


donde dice:
When the Wait For keyword is called, the sub is paused and the internal events dispatcher takes care to resume it when the event is raised. If the event is never raised then the sub will never be resumed. The program will still be completely responsive.
If Wait For is later called with the same event then the new sub instance will replace the previous one.
 

edgar_ortiz

Active Member
Licensed User
Longtime User
Aqui te explica mejor el Wait For.


donde dice:

Mi estimado @oparra

Ya también lo leí y aun sigo "perdido"... lo seguiré leyendo.

Tomando en cuenta TU habilidad "educativa" y Si estás de "Buenas" y Si tienes tiempo, sería genial si te preparas un proyecto para Tutorial en español.

Saludos,

Edgar
 

josejad

Expert
Licensed User
Longtime User
Ahora definitivamente ya estoy mas confundido... NO entiendo la diferencia entre
Hola Edgar:

La diferencia entre esos dos ejemplos es simplemente el bucle.
En uno hace, por ejemplo:
B4X:
Dim i as int
i = 0
log(i)
i = 1
log(i)

Y en el otro hace:
B4X:
Dim i as int
for i = 0 to 1
  log(i)
next

No es más que eso.
Cuando estás ejecutando código y llamas a una sub, en este caso j.Download, el código sigue ejecutándose, por lo tanto JobDone puede ocurrir cuando ya has terminado en tu sub, o el usuario haya ejecutado otra tarea.
Con Wait For la sub no sigue ejecutándose, sino que se "queda esperando" a que el evento JobDone se dispare y entonces tu sub principal sigue ejecutándose desde donde estaba.


para respetar la integridad de la información, primero debo cargar los países, cuando estos ya estén cargados en la base de datos, ya puedo cargar los departamentos de cada país y cuando los departamentos de cada país ya estén cargados, ya puedo cargar los municipios de cada departamento de cada país.

Para hacer lo que quieres, tendrías que ir esperando a que cada sub que llamas termina, antes de llamar a la otra, por lo que sería algo como:

B4X:
Sub CargarPaises As ResumableSub'Devolvemos true o false si se han leído correctamente los países
   'Tu código para cargar los países

  If SeHanCargadoOk Then
     return True
  else
      return False
  end if
End Sub

Sub CargarDepartamentos (pais as String) as ResumableSub
  'Tu código para cargar los departamentos
  If SeHanCargadoOk Then
     return True
  else
      return False
  end if
End Sub


Sub CargarMunicipios (departamento as string) as ResumableSub 'Puedes devolver true o false si se cargan bien, o devolver la lista de municipios
'Cargas los municipios

   .....
  If SeHanCargadoOk Then
      ListaMuncipios = MunicipiosCargados
     return True
  else
      return False
  end if
End Sub

'Código principal
'Mostrar por ejemplo un  B4XLoadingIndicator
Wait For (CargarPaises) Complete (SuccessPaises as Boolean) 'SuccessPaises sería True o False según lo que devuelva Cargar Países
If SuccessPaises Then
  Wait For (CargarDepartamentos (paisLeído)) Complete (SuccessDepartamentos as Boolean)
    If SuccessDepartamentos Then
        Wait for (CargarMunicipios(departamentoLeído)) Complete (SuccessMunicipios as Boolean)
         if SuccessMunicipios Then
             Log("Se han cargado correctamente")
         else
             Log("No se han cargado los municipios")
          end if
    else
        Log("No se han cargado los departamentos")
    end if
Else
  Log("No se han podido cargarlos países")
End If
'Ocultar tu  B4XLoadingIndicator
end Sub

Ojo, como estás haciendo procesos que se quedan en espera, es importante mostrar algún mensaje indicador de carga al usuario para que no crea que durante esos segundos que dura el proceso, la app se ha bloqueado. (Por ejemplo un B4XLoadingIndicator)
No sé si me he explicado muy bien... y algún fallito puede haber


saludos,
 
Last edited:

TILogistic

Expert
Licensed User
Longtime User
Mi estimado @oparra

Ya también lo leí y aun sigo "perdido"... lo seguiré leyendo.

Tomando en cuenta TU habilidad "educativa" y Si estás de "Buenas" y Si tienes tiempo, sería genial si te preparas un proyecto para Tutorial en español.

Saludos,

Edgar

Cuando se llama a la palabra clave Wait For, el sub se detiene y el despachador de eventos internos se encarga de reanudarlo cuando se genera el evento. Si el evento nunca se genera, la suscripción nunca se reanudará. El programa seguirá respondiendo completamente.

Si luego se llama a Wait For con el mismo evento, la nueva subinstancia reemplazará a la anterior.

Digamos que queremos crear un sub que descarga una imagen y la configura como ImageView:

''Mal ejemplo. No lo use.
Wait For JobDone(job As HttpJob)

B4X:
Sub DownloadImage(Link As String, iv As ImageView)
   Dim job As HttpJob
   job.Initialize("", Me) 'note that the name parameter is no longer needed.
   job.Download(Link)
   Wait For JobDone(job As HttpJob)
   If job.Success Then
     iv.SetImage (job.GetBitmap) 'replace with iv.Bitmap = job.GetBitmap in B4A / B4i
   End If
   job.Release
End Sub

Funcionará correctamente si lo llamamos una vez (más correctamente, si no lo volvemos a llamar antes de que se complete la llamada anterior).

Si lo llamamos así:

B4X:
DownloadImage("https://www.b4x.com/images3/android.png", ImageView1)
DownloadImage("https://www.b4x.com/images3/apple.png", ImageView2)

Entonces solo se mostrará la segunda imagen porque la segunda llamada a Wait For JobDone sobrescribirá la anterior.

Esto nos lleva a la segunda variante de Wait For.

Para resolver este problema, Wait For puede distinguir entre eventos según el remitente del evento.

Esto se hace con un parámetro opcional:


Wait For (<sender>) <event signature>

Ejemplo:
Wait For (job) JobDone(job As HttpJob)

B4X:
'Good example. Use.
Sub DownloadImage(Link As String, iv As ImageView)
   Dim job As HttpJob
   job.Initialize("", Me) 'note that the name parameter is no longer needed.
   job.Download(Link)
   Wait For (job) JobDone(job As HttpJob)
   If job.Success Then
     iv.SetImage (job.GetBitmap) 'replace with iv.Bitmap = job.GetBitmap in B4A / B4i
   End If
   job.Release
End Sub

Con el código anterior, cada subinstancia reanudable esperará un evento diferente y no se verá afectada por otras llamadas.

Google Traductor!! 😁😁😁😁😁


Saludos,
 
Last edited:

TILogistic

Expert
Licensed User
Longtime User
Ahora bien, lo que comento @José J. Aguilar es una forma de hacer.

La forma como lo hacemos nosotros es a través de un solo sub, el cual enviamos un link y nos devuelve un Json (REST API).

Esto nos evita tener que crear varias sub de consultas.

Note:
Similar a como ejemplo anterior para cargar imagines, pero llamadas a REST API.

Se entiende??

Saludos,
 
Last edited:
Top