Italian Aspettare che una routine sia davvero terminata (Wait for... ancora tu!)

Sabotto

Active Member
Licensed User
Ho una situazione (penso) classica: Voglio proseguire un codice solo se una delle routine chiamate sia effettivamente terminata
Nello specifico, scarico una pagina HTML da un sito e la memorizzo in una string 'CodiceHTML'
Solo dopo che tale string sia effettivamente valorizzata devo proseguire col programma.
Immagino ci voglia un 'Wait for' ma questo comando non riesco proprio a capirlo (facendo esaurire alcuni di voi in un altro post...qui).
Al momento ho risolto ritardando l'esecuzione delle istruzioni che seguono quella che mi restituisce 'CodiceHTML', con uno Sleep.
Però vorrei imparare perchè penso che questo mio ripiego sia uno po un accrocchio, funzionante, ma pur sempre un accrocchio.

Ecco il codice interessato
B4X:
Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("Layout")

    Avvio
    
End Sub

Sub Avvio
    
    EstraePaginaHTML
    
    'Wait for JobDone (Job As HttpJob) 'così non funziona'
    Sleep(2000)        ' così funziona e mi ritrovo CodiceHTML non vuoto
    
    If CodiceHTML<>"" Then
        RipuliscoHTML
    Else
        Msgbox("Non sono riuscito a ricavare CodiceHTML!","")
        Return
    End If
    
    'continuo con alktre routine se sopra è andato tutto ok'
    
End Sub

Sub EstraePaginaHTML
    
    oHttpClient.Initialize("oHttpClient")      ' client http
    Dim oHTTPJob As HttpJob
    oHTTPJob.Initialize("oHTTPJob", Me)
    oHTTPJob.Download("https://www.estrazionedellotto.it/")
        
End Sub

Sub JobDone (Job As HttpJob)
 
    Log("Evento JobName = " & Job.JobName & ", Success = " & Job.Success)
    If Job.Success And Job.JobName= "oHTTPJob" Then
        CodiceHTML =Job.getstring
    Else
        Log("Error: " & Job.ErrorMessage)
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
 
    Job.Release
    
End Sub
 

Alessandro71

Well-Known Member
Licensed User
Longtime User
 

Sabotto

Active Member
Licensed User
Ho provato a creare un esempio simile al link (vedi Routine Scarica) ma niente. Se metto sleep va altrimenti no

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    Dim CodiceHTML As String
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    Avvio
End Sub

Sub Avvio
    
    Scarica
    'Sleep(2000) ' con questo sleep funziona, (CodiceHTML non vuoto), senza no
    If CodiceHTML<>"" Then
        'Ok tutto bene
    Else
        ' Codicehtml vuoto
    End If
    
End Sub

Sub Scarica

    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download("https://www.estrazionedellotto.it/")
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        CodiceHTML=j.GetString
    End If
    j.Release

End Sub
 

Star-Dust

Expert
Licensed User
Longtime User
B4X:
Sub Avvio
    Wait For (Scarica) Complete (Result As Boolean)
    If Result Then
        'Ok tutto bene
    Else
        ' Codicehtml vuoto
    End If
End Sub

Sub Scarica As ResumableSub
    Dim Rs As Boolean
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download("https://www.estrazionedellotto.it/")
    Wait For (j) JobDone(j As HttpJob)
    Rs=j.Success
    If j.Success Then
        CodiceHTML=j.GetString
    End If
    j.Release

    Return Rs
End Sub
 

Alessandro71

Well-Known Member
Licensed User
Longtime User
prova con qualcosa di simile a

B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    Dim CodiceHTML As String
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    Avvio
End Sub

Sub Avvio
    
    Wait For (Scarica) Complete (Success As Boolean)
    If CodiceHTML<>"" Then
        'Ok tutto bene
    Else
        ' Codicehtml vuoto
    End If
    
End Sub

Sub Scarica As ResumableSub

    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download("https://www.estrazionedellotto.it/")
    Wait For (j) JobDone(j As HttpJob)
    If j.Success Then
        CodiceHTML=j.GetString
    End If
    j.Release
    Return True
End Sub
 

Sabotto

Active Member
Licensed User
B4X:
Sub Avvio
    Wait For (Scarica) Complete (Result As Boolean)
    If Result Then
        'Ok tutto bene
    Else
        ' Codicehtml vuoto
    End If
End Sub

Sub Scarica As ResumableSub
    Dim Rs As Boolean
    Dim j As HttpJob
    j.Initialize("", Me)
    j.Download("https://www.estrazionedellotto.it/")
    Wait For (j) JobDone(j As HttpJob)
    Rs=j.Success
    If j.Success Then
        CodiceHTML=j.GetString
    End If
    j.Release

    Return Rs
End Sub
si. ora va bene.
Approfitto, restando in argomento: se al posto della routine Scarica' che usa un Wait for di un evento del Job, ci fosse una routine diversa, che fa operazioni senza eventi scatenati, (ad esempio scrivere un file grande o altro, o che comunque valorizza un qualcosa/variabile, ecc che alla sua uscita con End Sub potrebbe non essere ancora 'pronto' ...) come andrebbe implementata la stessa affinchè io sia sicuro che abbia finito?
Esempio
B4X:
Sub Avvio

    Wait For (RoutineCheScriveFileGrande) Complete (Result As Boolean)
    'qui devo aspettare che il file sia stato scritto'
    If Result Then
        'Ok tutto bene
    Else
        ' NOn riuscito
    End If

End Sub


Sub RoutineCheScriveFileGrande As ResumableSub

  
    'Scrivo file molto grande
    ' come potrei usare Wait For?
  
    'qui esco ma il file potrebbe ancora non essere pronto'
End Sub
 

Star-Dust

Expert
Licensed User
Longtime User
Se una sub non usa le Resumable Sub, non ci sono modifiche da fare alla programmazione tradizionale. Al completamento della sub il flusso di esecuzione ritorna al livello superiore.

B4X:
Sub Avvio
   Scrivifile
End Sub


Sub ScriviFile

    'Codice non asincrono
End Sub

Ovviamente la scrittura del file deve usare un metodo non asincrono. Se usi un metodo Asincrono allora stai usando le ResumableSub.
 

Sagenut

Expert
Licensed User
Longtime User
Se vuoi essere davvero sicuro che una Sub sia stata eseguita fino in fondo prima di proseguire puoi fare così
B4X:
Sub facciocose
    'Esegui tutte le operazioni che vuoi
    'anche con dei Wait For o degli Sleep
    
    CallSubDelayed(Me, "HoFinito")
End Sub

'Per chiamare la Sub e attendere
facciocose 'esegue la Sub
Wait For HoFinito 'Attende la chiamata CallSubDelayed
Può essere anche una Resumable con dei Wait For o degli Sleep.
L'esecuzione non proseguirà perchè i Wait For e gli Sleep si fermeranno al
B4X:
Wait For HoFinito
 

Sagenut

Expert
Licensed User
Longtime User
Diciamo che questo non è proprio un metodo pulito, però può tornare utile.
 

Sagenut

Expert
Licensed User
Longtime User
Se però dovesse ritornare un valore non andrebbe bene perchè il Return eviterebbe il CallSubDelayed e quindi il flusso resterebbe bloccato. No?
 

Sagenut

Expert
Licensed User
Longtime User
B4X:
Sub facciocose (pippo as String) as String
    'Esegui tutte le operazioni che vuoi
    'anche con dei Wait For o degli Sleep
    maria = pippo
    Return maria 'la Sub finisce quì e il flusso si blocca perchè non viene eseguito
                 'il CallSubDelayed
   
    CallSubDelayed(Me, "HoFinito")
End Sub

'Per chiamare la Sub e attendere
facciocose 'esegue la Sub
'IL RETURN MUORE QUI'
Wait For HoFinito 'Attende la chiamata CallSubDelayed
In un caso come questo il flusso si bloccherebbe no?
 

LucaMs

Expert
Licensed User
Longtime User
Intanto se volessi un risultato dalla tua facciocose dovrei chiarmarla così:
Nome = facciocose("ugo")
Wait For HoFinito

Ma migliorandola un po' (proprio pippo dovevi chiamare il parametro? 😄)
B4X:
Sub facciocose (pippo as String) as String
    'Esegui tutte le operazioni che vuoi
    'anche con dei Wait For o degli Sleep
    Dim maria As String = pippo
    CallSubDelayed2(Me, "HoFinito", maria)
End Sub

'Per chiamare la Sub e attendere
facciocose 'esegue la Sub
Wait For HoFinito(NomeRestituito As String) 'Attende la chiamata CallSubDelayed
Nome = NomeRestituito

Non l'ho provato, ovviamente, né c'ho ragionato molto, si può fare anche meglio.
Anzi, ora premo "Post reply" e POI rileggo, hehehe

P.S. A occhio sembra giusta.
 

Sagenut

Expert
Licensed User
Longtime User
Mi ero perso in una cavolata.
E' ora di appendere la tastiera al chiodo. 🤣 🤣 🤣
 

LucaMs

Expert
Licensed User
Longtime User
Oh, guarda caso proprio adesso ho un problemino con le resumable (a parte che ce n'è uno molto più grave... va beh, eventualmente ve ne parlerò).

Ho una classe in cui nella Initialize dovrei effettuare una chiamata tramite Wait For. In questo modo, però, la Initialize diventerebbe una Resumable e questo non è consentito.

Resumable: gioie e dolori (più gioie, però).
 
Top