17 messaggi dal 30 marzo 2017
ciao gino
ho modificato il sorgente aggiungendo alcuni debug.print per essere certo che i task "morissero"....
già prima, in ogni caso, la routine funzionava
Ecco il sorgente : basta creare un form e tre textbox
grazie per la pazienza !

Imports System.Diagnostics
Imports System.Globalization
Imports System.Threading.Tasks

Public Class Form1

    Dim MemUsata As String = ""
    Dim ScriviVecchioPicco As Integer = 0
    Dim TestOrario As String = ""
    Dim VecchioPicco As Integer = 0
    Dim FineTask As Boolean = True
    Public Delegate Sub mydel(ByVal uscita As String)



    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        Me.Show()
        Me.CenterToScreen()

        Timer1.Interval = 50
        Timer1.Enabled = True

    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick

        Timer1.Enabled = False

        Dim TEST_TASK_1 As New Task(AddressOf ORARIO)
        TEST_TASK_1.Start()
        Debug.Print("task 1 ini " & TEST_TASK_1.IsCompleted)
        Dim dlg As mydel
        dlg = New mydel(AddressOf ORARIO)
        dlg.Invoke("")
        TextBox1.Text = TestOrario

        Dim TEST_TASK_2 As New Task(AddressOf MEM_USATA)
        TEST_TASK_2.Start()
        Debug.Print("task 2 ini " & TEST_TASK_2.IsCompleted)
        Dim dlg2 As mydel
        dlg2 = New mydel(AddressOf MEM_USATA)
        dlg2.Invoke("")
        TextBox3.AppendText(MemUsata)

        If ScriviVecchioPicco = 1 Then
            ScriviVecchioPicco = 0
            TextBox2.AppendText(MemUsata)
        End If

        While FineTask = Timer1.Enabled = False

            If TEST_TASK_1.IsCompleted = True And TEST_TASK_2.IsCompleted = True Then
                TEST_TASK_1.Dispose()
                TEST_TASK_2.Dispose()
                Timer1.Enabled = True
            End If

        End While

        Debug.Print("task 1 " & TEST_TASK_1.IsCompleted)
        Debug.Print("task 2 " & TEST_TASK_2.IsCompleted)

    End Sub

    Sub ORARIO()
        TestOrario = Format(Now.ToString("G", New CultureInfo("it-IT")))
    End Sub

    Sub MEM_USATA()

        Dim c As Process = Process.GetCurrentProcess()
        MemUsata = String.Empty
        MemUsata &= Format(Now.ToString("G", New CultureInfo("it-IT"))) & " --- "
        MemUsata &= "WS: " & c.WorkingSet / 1024 & " K - "
        MemUsata &= "VM: " & c.PagedMemorySize / 1024 & " K - "
        MemUsata &= "GC: " & GC.GetTotalMemory(True) & " b" & vbCrLf

        If (c.WorkingSet / 1024) > VecchioPicco Then
            VecchioPicco = c.WorkingSet / 1024
            ScriviVecchioPicco = 1
        End If

    End Sub

End Class


per la seconda tua soluzione debbo studiare, perchè non conosco la questione...

infine : girando qui e lì o trovato questo documento che mi ha lasciato basito : credo che non ci sia una soluzione diretta ma solo work-around che aggirano il problema

https://www.ben-morris.com/memory-leaks-in-net-applications-yes-they-happen-all-the-time/
Modificato da fotosettore2 il 21 marzo 2020 21:10 -
135 messaggi dal 01 febbraio 2017
fotosettore2 ha scritto:
ciao gino
ho modificato il sorgente aggiungendo alcuni debug.print per essere certo che i task "morissero"....
già prima, in ogni caso, la routine funzionava
Ecco il sorgente : basta creare un form e tre textbox
grazie per la pazienza !

Imports System.Diagnostics
Imports System.Globalization
Imports System.Threading.Tasks

Public Class Form1

    Dim MemUsata As String = ""
    Dim ScriviVecchioPicco As Integer = 0
    Dim TestOrario As String = ""
    Dim VecchioPicco As Integer = 0
    Dim FineTask As Boolean = True
    Public Delegate Sub mydel(ByVal uscita As String)



    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        Me.Show()
        Me.CenterToScreen()

        Timer1.Interval = 50
        Timer1.Enabled = True

    End Sub

    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick

        Timer1.Enabled = False

        Dim TEST_TASK_1 As New Task(AddressOf ORARIO)
        TEST_TASK_1.Start()
        Debug.Print("task 1 ini " & TEST_TASK_1.IsCompleted)
        Dim dlg As mydel
        dlg = New mydel(AddressOf ORARIO)
        dlg.Invoke("")
        TextBox1.Text = TestOrario

        Dim TEST_TASK_2 As New Task(AddressOf MEM_USATA)
        TEST_TASK_2.Start()
        Debug.Print("task 2 ini " & TEST_TASK_2.IsCompleted)
        Dim dlg2 As mydel
        dlg2 = New mydel(AddressOf MEM_USATA)
        dlg2.Invoke("")
        TextBox3.AppendText(MemUsata)

        If ScriviVecchioPicco = 1 Then
            ScriviVecchioPicco = 0
            TextBox2.AppendText(MemUsata)
        End If

        While FineTask = Timer1.Enabled = False

            If TEST_TASK_1.IsCompleted = True And TEST_TASK_2.IsCompleted = True Then
                TEST_TASK_1.Dispose()
                TEST_TASK_2.Dispose()
                Timer1.Enabled = True
            End If

        End While

        Debug.Print("task 1 " & TEST_TASK_1.IsCompleted)
        Debug.Print("task 2 " & TEST_TASK_2.IsCompleted)

    End Sub

    Sub ORARIO()
        TestOrario = Format(Now.ToString("G", New CultureInfo("it-IT")))
    End Sub

    Sub MEM_USATA()

        Dim c As Process = Process.GetCurrentProcess()
        MemUsata = String.Empty
        MemUsata &= Format(Now.ToString("G", New CultureInfo("it-IT"))) & " --- "
        MemUsata &= "WS: " & c.WorkingSet / 1024 & " K - "
        MemUsata &= "VM: " & c.PagedMemorySize / 1024 & " K - "
        MemUsata &= "GC: " & GC.GetTotalMemory(True) & " b" & vbCrLf

        If (c.WorkingSet / 1024) > VecchioPicco Then
            VecchioPicco = c.WorkingSet / 1024
            ScriviVecchioPicco = 1
        End If

    End Sub

End Class


per la seconda tua soluzione debbo studiare, perchè non conosco la questione...

infine : girando qui e lì o trovato questo documento che mi ha lasciato basito : credo che non ci sia una soluzione diretta ma solo work-around che aggirano il problema

https://www.ben-morris.com/memory-leaks-in-net-applications-yes-they-happen-all-the-time/
Modificato da fotosettore2 il 21 marzo 2020 21:10 -


Uhmmm ... a prima vista vedo tanti delegate e non ne trovo l'utilità (vedo che li usi anche per una semplice SUB).
La prossima settimana sarò al PC e potrò provare meglio il tuo codice, intanto oltre alla seconda soluzione che ti ho dato (dichiarare una sola volta il Task e riutilizzarlo sempre), ti ricordo che in vb2019 (ma anche nel 2015) se nn ricordo male c'è il costrutto AWAIT, nato proprio per snellire la gestione dei task asincroni, che ti solleva dai relativi 'problemini' e non usi i delegate.

Infine per il link segnalato ... mi pare di capire che parla di C#, la cui gestione della memoria è completamente diversa da VB, anche se si appoggia nel Framewrok comune. Lì non si capisce se il problema sia di .NET o di C#.

A dopo.
Gino.

UNSTRING identifier-1 id-2 id-3
DELIMITED BY [ALL] OR [ALL] literal-1 lit-2
INTO {id-4 [DELIMITER IN id-5]
[COUNT IN id-6]}
[WITH POINTER id-7]
[TALLYING IN id-8]
[ON OVERFLOW imperative-statement-1]
[NOT ON OVERFLOW imper-2]
[END-UNSTRING]
17 messaggi dal 30 marzo 2017
uso i delegate perchè nel mio programma originale ho bisogno di far vedere a video variabili che si modificano continuamente. le routines stanno in un modulo e nel main c'è la grafica e lo start dei thread e/o task.
comunque purtroppo anche senza i delegate il problema di base resta.

adesso mi metto a studiare le cose per le quali mi hai dato input.

infine, da quello che ho visto, il link parla di tutto il .net, facendo riferimento indicativo al c++, al c# ma anche a java, tralasciando vb perchè da tutti, sopratutto dai puristi, viene considerato una schifezza (mai capito perchè) ... vabbè ma questa è un'altra storia...

come funziona la memoria su vb e c non lo so, ecco anche il motivo della mia presenza qui.

ok gino, faccio ulteriori prove e nel frattempo attendo un tuo test settimana prossima.
Modificato da fotosettore2 il 22 marzo 2020 12:26 -
135 messaggi dal 01 febbraio 2017
fotosettore2 ha scritto:
uso i delegate perchè nel mio programma originale ho bisogno di far vedere a video variabili che si modificano continuamente. le routines stanno in un modulo e nel main c'è la grafica e lo start dei thread e/o task.
comunque purtroppo anche senza i delegate il problema di base resta.

adesso mi metto a studiare le cose per le quali mi hai dato input.

infine, da quello che ho visto, il link parla di tutto il .net, facendo riferimento indicativo al c++, al c# ma anche a java, tralasciando vb perchè da tutti, sopratutto dai puristi, viene considerato una schifezza (mai capito perchè) ... vabbè ma questa è un'altra storia...

come funziona la memoria su vb e c non lo so, ecco anche il motivo della mia presenza qui.

ok gino, faccio ulteriori prove e nel frattempo attendo un tuo test settimana prossima.
Modificato da fotosettore2 il 22 marzo 2020 12:26 -


Rieccomi, ho fatto alcune prove sul tuo codice, premesso che mi da alcune funzioni come obsolete, non riesco ad avere il risultato nella textbox3. Dopo 20 minuti viene azzerato e nn mi piace.
Non mi piace per come è strutturato il codice, perchè (e questo l'ho detto fin dal primo momento) i task possono essere in esecuzione contemporaneamente, sia l'uno con due, sia fra loro e come se non bastasse possono verificarsi condizioni di deadlock ...
Mi spiego meglio, fai finta che il task 2, che è quello che esegue più operazioni, viene lanciato di nuovo dal timer, prima ancora di aver finito la sua esecuzione ... il secondo task tenterà di scrivere sulla variabile Memusata che è in uso dal primo e quindi ... patatrocchio.
Questo può essere evitato usando una variabile dedicata in ogni task, ma io cambierei totalmente approccio.

Soluzioni :
1) Usa 2 task friend, li dichiari una volta ed eviti di distruggerli ogni volta
2) Usa il costrutto AWAIT/ASYNC nato per questo scopo
3) sei i task da eseguire sono solamente due, usa due timer scollegati, ed eseguono una SUB indipendentemente ognuno e te ne esci dalla malattia
4) Rendi autonome le due fuznioni, se proprio vuoi usare questa tecnica, facendo la relativa dispose AUTONOMAMENTE .. come scritto prima sarà molto difficile che i due task terminino nello stesso istante
5) butta sti delegate o vai a gestire a manuzza la pulizia delle memoria, quando finisce l'esecuzione ogni task (devi gestire una coda di operazioni), perchè dalle mie prove, il PRINT.Debug che hai inserito a volte da false, quindi significa che sono ancora attivi.

PS. Nei miei tests, dopo 40 minuti di esecuzione non ho visto nessun incremento abnorme della memoria.
PPS. Non mi piace molto che immetti un ciclo di attesa dentro un'operazione che è schedulata per essere eseguita ogni 50 millisecondi ...
Ciao
Gino

UNSTRING identifier-1 id-2 id-3
DELIMITED BY [ALL] OR [ALL] literal-1 lit-2
INTO {id-4 [DELIMITER IN id-5]
[COUNT IN id-6]}
[WITH POINTER id-7]
[TALLYING IN id-8]
[ON OVERFLOW imperative-statement-1]
[NOT ON OVERFLOW imper-2]
[END-UNSTRING]
17 messaggi dal 30 marzo 2017
ciao gino
anzitutto grazie per la pazienza che stai avendo

allora ...io non sono riuscito a trovare nulla in relazione a thread friends ma voglio vedere meglio perchè purtroppo quello che ho notato che sul web ci sono esempi ma molto farraginosi e teorici e per me è un dramma.
prima cosa che volevo dirti che a me il textbox3 si riempe senza problemi ... non capisco perchè a te no.
seconda cosa : tu mi dici : "il task 2, che è quello che esegue più operazioni, viene lanciato di nuovo dal timer".
ma se io, appena lanciato il timer lo blocco con timer1.enabled = false, che diventa true fino a quando non si esce dal while, come fa a ripartire ?
credimi ...fammi capire dove sbaglio perchè una cassa di birra è pronta per mandarla al tuo domicilio.

In ogni caso mi dici che l'approccio è sbagliato e non posso far altro che abbassare la testa e prendere atto, casomai ce ne fosse ancora bisogno, che sono un pivello nella programmazione e più di tanto, da me stesso, non posso pretendere.
ti chiedo quindi di postarmi un esempio (magari quello che hai fatto e modificato tu) che possa farmi capire come iniziare a programmare questa cosa in modo preciso e/o link di riferimento con esempi per utonti come il sottoscritto

nel frattempo mi rimetto alla ricerca
attendo tue info
grazie
peppe

p.s. stasera (ri)leggo in modo CERTOSINO il capitolo 9 di "VISUAL BASIC 2015" di Bochiccio e company, nel quale si parla di multithreading
Modificato da fotosettore2 il 25 marzo 2020 19:13 -
135 messaggi dal 01 febbraio 2017
fotosettore2 ha scritto:
ciao gino
anzitutto grazie per la pazienza che stai avendo

allora ...

p.s. stasera (ri)leggo in modo CERTOSINO il capitolo 9 di "VISUAL BASIC 2015" di Bochiccio e company, nel quale si parla di multithreading
Modificato da fotosettore2 il 25 marzo 2020 19:13 -

Dai anche un occhio a Pag. 104 che parla dei Delegate e Pag 191 Async Await ... eheheheheh ...


seconda cosa : tu mi dici : "il task 2, che è quello che esegue più operazioni, viene lanciato di nuovo dal timer".
ma se io, appena lanciato il timer lo blocco con timer1.enabled = false, che diventa true fino a quando non si esce dal while, come fa a ripartire ?
credimi ...fammi capire dove sbaglio perchè una cassa di birra è pronta per mandarla al tuo domicilio.

Appena attivato il timer, quello comincia a 'sparare' eventi e magari ancora deve iniziare l'esecuzione della SUB e prima di eseguire il timer=false ha già 20 sub in coda ... purtroppo (secondo me) è proprio impostato male.

Poi ripeto c'è sempre il problema della memoria che viene quindi riscritta in contemporanea.


In ogni caso mi dici che l'approccio è sbagliato e non posso far altro che abbassare la testa e prendere atto, casomai ce ne fosse ancora bisogno, che sono un pivello nella programmazione e più di tanto, da me stesso, non posso pretendere.


La cosa più semplice allora è quella dei due timer scollegati, se sono solo task da eseguite in maniera indipendente l'uno dall'altro.

Neanche io sono una cima, pur essendo prossimo alla pensione sono molto 'giovane' come .NET ed il Basic lo avevo fatto a scuola. La mia esperienza è tutta in ambito Mainframe in COBOL, (che era il principe dei linguaggi una volta, essendo multi OS), RPG e ...

Il debug di un pgm con funzioni asincrone è molto problematico e non affidabile, te lo dice uno che ci ha sbattuto la testa.

Su quel libro troverai diversi spunti e soluzioni ...

A tempo libero vedo se posso mettere in piedi qualcosa meno lontano possibile dal tuo codice.

Ciao.
Gino

UNSTRING identifier-1 id-2 id-3
DELIMITED BY [ALL] OR [ALL] literal-1 lit-2
INTO {id-4 [DELIMITER IN id-5]
[COUNT IN id-6]}
[WITH POINTER id-7]
[TALLYING IN id-8]
[ON OVERFLOW imperative-statement-1]
[NOT ON OVERFLOW imper-2]
[END-UNSTRING]
17 messaggi dal 30 marzo 2017
>>> pur essendo prossimo alla pensione

sono nato nel 1960 ... è probabile che abbiamo ascoltato la stessa musica, ai nostri tempi

mi metto all'opera e comincio a studiare meglio il tutto

grazie ancora

p.s. i threads nel programma originale sono tutti gestiti da timers separati e sono circa una 10na;
di certo ho combinato qualche casino ....
17 messaggi dal 30 marzo 2017
ciao gino
sto facendo delle prove sulla base dei codici di esempio del libro di bochicchio.
alcuni mi danno errore di compilazione ed ho dovuto modificarli nella sintassi ... boh ...

quello che comunque voglio far intendere bene è la lista delle mie necessità e del risultato, cioè, che io debbo raggiungere.
la cosa sembrava abbastanza semplice ma da quello che ho visto è invece (per me) un pandemonio.
Cosa mi servirebbe ?
E' presto detto

debbo creare un programma nel quale girano vari thread (o task, ancora non ho capito) INDIPENDENTI

uno serve a fare le richieste all'inverter tramite la seriale o la usb, crea delle variabili pubbliche sulla base della stringa ricevuta : questo deve avvenire ripetutamente ogni secondo

uno serve a visualizzare a video le variabili suddette; anche questo deve avvenire ogni secondo

uno serve ad inviare alcune delle variabile suddette al cloud; questo avviene ogni minuto

uno serve ad accendere o spegnere un relè a seconda del valore di alcune variabili suddette; questo deVe avvenire ogni 20 secondi

etc etc etc
tutto deve avvenire in modo INDIPENDENTE, cioè ognuno fa il suo lavoro e tutti si basano sulle variabili prodotte dal primo thread.

Ho notato che la produzione di questi thread mi fa gonfiare la memoria, come detto nel primo messaggio di questo lungo discorso

Sto sbagliando qualcosa, come detto ...

Questo messaggio solo per far capire meglio cosa ho intenzione di risolvere.

grazie ancora
ciao

ps dopo aver letto qualche pagina del manuale volevo chiarire che:
NESSUN THREAD O TASK DEVE ATTENDERE L'ESITO DEGLI ALTRI : OGNUNO LAVORA PER CONTO SUO, SECONDO I TEMPI DATI DAI RISPETTIVI TIMERS.
gli esempi riportati, purtroppo, non prevedono una iterazione: vengono eseguiti solo una volta e quindi non sono validi per le mie problematiche.
Modificato da fotosettore2 il 26 marzo 2020 11:29 -

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.