Italian Wait For

moore_it

Well-Known Member
Licensed User
Longtime User
Buongiorno a tutti,

chi mi può gentilmente spiegare come bloccare una sub fino a che non succede un qualcosa che decido io.
Nel senso, ho un'attività da fare al termine della quale scrivo un log e solo dopo che il log (sia che sia bene, sia che sia male) è stato scritto passo all'attività successiva.
Premetto che sto lavorando all'interno di un ciclo for dove leggo n attività, e il tutto è gestito da un timer che mi lancia il ciclo for a orari stabiliti.

Io avrei fatto in questo modo:

writelog (sub)
wait for writelog_completed (sub richiamata da writelog)

ma a quanto pare ho dei risultati stranissimi.

Spero di essermi spiegato e soprattutto grazie a chi mi può aiutare.

Grazie
 

Elric

Well-Known Member
Licensed User
Qui c'è il tutorial: https://www.b4x.com/android/forum/threads/b4x-resumable-subs-sleep-wait-for.78601/

Puoi [codice non testato - magari ho sbagliato qualcosa]:
B4X:
Private Sub LogGenerator
    Private myLog as String = "This is a string"
    Wait For (writelog(myLog)) Complete
End Sub

Private Sub writelog(x as String)
    log (x)
End Sub

oppure


B4X:
Private Sub LogGenerator
    Private myLog as String = "This is a string"
    Wait For (writelog(myLog)) Complete (Result as Boolean)

    If Result = True Then
        Log("Log ok")
    Else
        Log("Log non-ok")
    End If
End Sub

Private Sub writelog(x as String)
    private success as Boolean
    log (x)
    If x <> "" Then
        success = True
    Else
        success = False
    End If
    Return success
End Sub

Edit: una Wait for senza "Return" è un'anomalia https://www.b4x.com/android/forum/threads/wait-for-complete.131363/post-827740.
 
Last edited:

moore_it

Well-Known Member
Licensed User
Longtime User
Ciao,

grazie per la risposta, scusa il ritardo.
Ho tentato e riletto per l'ennesima volta il tutorial ma il programma continua a girare a modo suo.

Come spiegavo io ho una lista di attività che devono essere eseguite leggendo i dati da una tableview.
Ad ogni minuto vado a leggere la tableview, se una riga entra nelle condizioni volute la aggiungo ad una lista.
La lista viene poi letta con un ciclo for e a seconda del tipo di attività eseguo :
l'invio di una e-mail o l'upload ad un server FTP o l'upload ad un server SFTP o il download da un server FTP o per finire un download da un server SFTP.
Il problema è che il primo giro, quale che sia, viene eseguito correttamente e poi come per magia il ciclo for si disattiva e quindi eseguo sempre e solo un'attività.

Grazie
 

LucaMs

Expert
Licensed User
Longtime User
B4X:
For Each Riga As String in lstRiga ' <--- ovviamente invento, è il loop sulla tua lista. Il tipo di Riga potrà essere anche diverso.
    Wait For(Attivita(Parametri As Map) Complete (Terminata As Boolean) '<--- Parametri dipende da te, è opzionale e potrebbe anche essere un array o altro.
Next

B4X:
Sub Attivita(Params As Map) As ResumableSub
    ' Fai ciò che devi fare.
    ' Ad esempio, un elemento di Params potrebbe essere il tipo di attività da eseguire e poi con una Select...!

    Dim TipoAttivita As String = Params.Get("TipoAttivita")
    Select TipoAttivita
        Case "FTP"
            ' ...
        Case "EMail"
            ' ....
    End Select

    Return True ' <--- non ha importanza se True o False. Dato che ho dichiarato Terminata come Boolean, restituire un Boolean, ma volendo tipi diversi.
End Sub
 
Last edited:

moore_it

Well-Known Member
Licensed User
Longtime User
Ciao LucaMs grazie per la risposta,

ho fatto le modifiche seguendo il tuo consiglio ma continuo ad eseguire la prima riga e poi esco ... non riesco proprio a capire.
 

Xfood

Expert
Licensed User
Anche io ancora non ho capito bene il funzionamento di wait for.??
 

moore_it

Well-Known Member
Licensed User
Longtime User
Adesso però ho un errore un indice ma non saprei dire quale ...

Errore nella linea: 540 (Main)
java.lang.IndexOutOfBoundsException: Index 1 out of bounds for length 0
at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:64)
at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:70)
at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:248)
at java.base/java.util.Objects.checkIndex(Objects.java:372)
at java.base/java.util.ArrayList.get(ArrayList.java:458)
at anywheresoftware.b4a.objects.collections.List.Get(List.java:105)
at b4j.example.main$ResumableSub_ReadActivities.resume(main.java:1733)
at anywheresoftware.b4a.shell.DebugResumableSub$DelegatableResumableSub.resumeAsUserSub(DebugResumableSub.java:47)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:632)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:234)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
at jdk.internal.reflect.GeneratedMethodAccessor11.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:91)
at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:98)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:78)
at anywheresoftware.b4a.shell.DebugResumableSub$DelegatableResumableSub.resume(DebugResumableSub.java:42)
at anywheresoftware.b4a.BA.checkAndRunWaitForEvent(BA.java:136)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:85)
at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:98)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:78)
at anywheresoftware.b4a.keywords.Common$3.run(Common.java:1086)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:834)
 

moore_it

Well-Known Member
Licensed User
Longtime User
Sono contento che ci sia ancora qualcuno che come me ci sta sbattendo la testa.
 

Star-Dust

Expert
Licensed User
Longtime User
moore manda un pezzo di codice cosi lo vediamo
 

Star-Dust

Expert
Licensed User
Longtime User
Ti invio il programma come faccio ?
Bastava solo il pezzo che genera errore per il momento. Sul forum inserisci il codice usando [ CODE ] [ / CODE]
 

moore_it

Well-Known Member
Licensed User
Longtime User
B4X:
 Sub RunActivity(o() As Object) As ResumableSub
    If o(28) = "O" Then
        Select Case o(14)
            Case "E"
                wait for ( OutSMTP(o) ) Complete (terminata As Boolean) 
            Case "F"
                wait for ( OutFTP(o) ) Complete (terminata As Boolean)
            Case "S"
                wait for ( OutSFTP(o) ) Complete (terminata As Boolean)
        End Select
    Else
        Select Case o(14)
            Case "F"
                wait for ( InFTP(o) ) complete (terminata As Boolean)
            Case "S"
                wait for ( InSFTP(o) ) Complete (terminata As Boolean)
        End Select
    End If
'    Dim pb As ProgressBar = o(12)
'    pb.Progress = 1
'    o(12) = pb
'    Dim cb As CheckBox = o(0)
'    cb.Checked = True
'    o(0) = cb
    Return True
End Sub
 

Star-Dust

Expert
Licensed User
Longtime User
Alla riga 25 del pezzo di codice (540 del programma)
Vorrei vedere InFTP e InSFTP e come chiami RunActivity. Perchè O è un array di Object e non di string?

Quale malfunzionamento da?

Mi pare che tu esamini una TableView riga per riga giusto? Fammi vedere questo ciclo
 

moore_it

Well-Known Member
Licensed User
Longtime User
Perchè ho un checkbox e una progressbar nella tabella che riporto nell'array di oggetti , mi lancia la prima attività e poi mi dà quell'errore.
Perlomeno ora prova ad andare aventi con le attività ...


B4X:
Private Sub OutFTP(o() As Object)As ResumableSub
	Dim lg As List 
	lg.Initialize
	DateTime.DateFormat = "yyyyMMdd"
	DateTime.TimeFormat = "HHmmdd"
	Dim lgl As List
	lgl.Initialize
	pbRow = o(12)
	pbRow.Progress = 0
	Dim la As Label = o(13)
	' scelta file da uploadare
	Dim l As List = File.ListFiles(o(20))
	If l.IsInitialized Then
		Dim ff As List
		ff.Initialize
		' selezione dei files da inviare
		For i = 0 To l.size-1
			Dim s As String = l.Get(i)
			Dim ss As String = s.ToUpperCase
			If File.IsDirectory(o(20),s) Then Continue
			' contiene il cliente
			If o(2) <> "" Then  
				If s.Contains(o(2)) Or ss.Contains(o(2)) Then
					' contiene il nome file 
					If o(3) <> "" Then
						If s.Contains(o(3)) Or ss.Contains(o(3)) Then
							ff.Add(s)
						End If
					Else
						' se non ho il nome del file ma c'è il cliente spedisco tutto al cliente
						ff.Add(s)
					End If						
				End If
			Else
			' contiene il nome file
				If o(3) <> "" Then
					If s.Contains(o(3)) Or ss.Contains(o(3)) Then
						ff.Add(s)
					End If
				Else
					' se non contiene il nome del file e nemmeno il nome del cliente invio tutto 
					' perchè spero sia una cartella esclusiva del cliente
					ff.Add(s)
				End If
			End If
		Next
		If ff.Size = 0 Then
			pbRow.Progress = 1
			la.Text = "Nessun file trovato."
			Globals.SetNodeImage(la,File.DirAssets,"warning.png",16,16,"LEFT")
			o(13) = la
			lg.add(MakeLogMap("W",la.Text,o(2),o(3),o(28)))	
		Else
			' devo zippare il file
			If Globals.IntegerToBoolean(o(27)) Then
				Globals.Zippo(o(20),ff,o(3)&".zip")
			End If
			' se ho richiesto la storicizzazione e lo zip 
			If Globals.IntegerToBoolean(o(27)) Then
				If o(19) <> "" Then
					Dim hpath As String =  o(19)&GetSystemProperty("file.separator","NF")&o(2)&GetSystemProperty("file.separator","NF")&o(3)
					File.MakeDir(o(20),hpath)
				End If
				For i = ff.Size-1 To 0 Step-1 
					Dim nf As String = ff.Get(i)
					File.Copy(o(20),nf,o(20)&GetSystemProperty("file.separator","NF")&hpath,nf&"_"&DateTime.Date(DateTime.Now)&DateTime.Time(DateTime.Now))
					File.Delete(o(20),nf)
					ff.RemoveAt(i)
				Next
				ff.Initialize
				ff.Add(o(3)&".zip")
			End If
			' richiesta fotografie
			If Globals.IntegerToBoolean(o(29)) Then
				' crea le foto del cliente o(2) cercandole nel path o(30) nel percorso locale o(19)
				Dim photofile As String = Globals.AddPhoto(o(2),o(30),o(20))
				If File.Exists(o(20),photofile) Then
					ff.Add(photofile)
				End If
			End If
			' invio i file in lista
			Dim mftp As tmFTP
			' inizilizzo
			mftp.Initialize(o(22),o(23),o(24),o(25))
			For n = 0 To ff.Size-1				
				Dim nf As String = ff.Get(n)	
				pbRow.Id = File.Size(o(20),nf)
				mftp.FTPUpload(o(20),nf,o(21)&nf,pbRow)
				wait for mftpupload_completed(success As String)
				If success <> "" Then
					la.Text = success
					Globals.SetNodeImage(la,File.DirAssets,"cancel.png",16,16,"LEFT")
					o(13) = la
					lg.Add(MakeLogMap("E",la.Text,o(2),o(3),o(28)))
				Else
					la.Text = "Inviato con successo il file "&nf&"."
					Globals.SetNodeImage(la,File.DirAssets,"accept.png",16,16,"LEFT")
					o(13) = la
					lg.Add(MakeLogMap("O",la.Text,o(2),o(3),o(28)))
				End If
			Next
			mftp.Close
			' se tutto ok passo alle opzioni successive
			For n = ff.Size-1 To 0 Step-1
				' devo storicizzare
				If o(19) <> "" And Globals.IntegerToBoolean(o(27)) = False Then
					Dim hpath As String =  o(19)&GetSystemProperty("file.separator","NF")&o(2)&GetSystemProperty("file.separator","NF")&o(3)
					File.MakeDir(o(20),hpath)
					Dim nf As String = ff.Get(n)
					File.Copy(o(20),nf,o(20)&GetSystemProperty("file.separator","NF")&hpath,nf&"_"&DateTime.Date(DateTime.Now)&DateTime.Time(DateTime.Now))
				End If
				' cancello
				File.Delete(o(20),nf)
				ff.RemoveAt(n)
			Next
		End If	
	Else
		la.Text = "Path locale non accessibile."
		Globals.SetNodeImage(la,File.DirAssets,"cancel.png",16,16,"LEFT")
		o(13) = la
		pbRow.Progress = 1
		lg.Add(MakeLogMap("E",la.Text,o(2),o(3),o(28)))
	End If
	WriteLogs(lg)
	Return True
End Sub
 

Star-Dust

Expert
Licensed User
Longtime User
Vorrei vedere il ciclo For che scandisce le righe della TableView
 

moore_it

Well-Known Member
Licensed User
Longtime User
Ecco la lettura della tabella, sono in realtà due una per gli invii ed una per le ricezioni che io leggo e attivo il checkbox che è quello che mi permette di selezionare le righe da inserire il una lista ...

B4X:
Private Sub SetActivities
	' creo la mia lista di attività
	RUNACTIVITIES.Initialize
	
	For i = 0 To ACTIVITIES.Size - 1
		Dim o() As Object = ACTIVITIES.Get(i)
		Dim cb As CheckBox = o(0)
		' controllo il giorno della settimana e l'ora
		For n = 5 To 11
			Dim day As CheckBox = o(n)
			If day.Checked And DateTime.GetDayOfWeek(DateTime.Now) = day.tag Then
				' data e ora
				If o(15) = NumberFormat2(DateTime.GetHour(DateTime.Now),2,0,0,False) And o(16) = NumberFormat2(DateTime.GetMinute(DateTime.Now),2,0,0,False) Then
					cb.Checked = True
					o(0) = cb
					RUNACTIVITIES.Add(o)
				' periodo in minuti
				Else if o(17) <> "00" And o(18) = "M" And minutes > 0 Then
					Dim count As Double = (minutes/o(17))
					Dim crt As String = NumberFormat2(count, 0, 2, 2, False)
					If  crt.Contains(".00") Then
						cb.Checked = True
						o(0) = cb
						RUNACTIVITIES.Add(o)
					End If
				' periodo in ore	
				else if o(17) <> "00"  And o(18) = "H" And hours > 0  Then
					Dim count As Double = (hours/o(17))
					Dim crt As String = NumberFormat2(count, 0, 2, 2, False)
					If  crt.Contains(".00") Then
						cb.Checked = True
						o(0) = cb
						RUNACTIVITIES.Add(o)
					End If
				End If
			End If
		Next		
	Next	
End Sub
 

Star-Dust

Expert
Licensed User
Longtime User
ACTIVITIES cos'è? La TableView?
 

moore_it

Well-Known Member
Licensed User
Longtime User
In effetti la lettura della tabella non avviene, quando carico i dati aggiungo ogni riga in una lista
 

Star-Dust

Expert
Licensed User
Longtime User
Sembra che una lista O() sia vuota, quindi non carichi bene i dati
 
Top