Visualizzazione dei risultati da 1 a 8 su 8
  1. #1
    Utente di HTML.it L'avatar di Veronica80
    Registrato dal
    May 2006
    Messaggi
    2,029

    [VB.NET] Background Worker con funzione ricorsiva

    Ciao a tutti!
    Ho sempre usato i BGW per passaggio dati da DB a DB inserendo il ciclo nell'evento DoWork ed hanno sempre funzionato alla grande!

    Ora però sto lavorando sulla copia di files, e dacchè le cartelle possono avere N sottocartelle ho creato una funzione ricorsiva che appunto richiama se stessa.

    Il problema è che infilarla nell'evento DoWork diventa un po complicato e mi sono bloccata....

    Qualcuno sa come gestire questo tipo di situazione?

    Grazie!!

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    23,887
    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    Ora però sto lavorando sulla copia di files, e dacchè le cartelle possono avere N sottocartelle ho creato una funzione ricorsiva che appunto richiama se stessa.
    [...]
    Il problema è che infilarla nell'evento DoWork diventa un po complicato e mi sono bloccata....
    Dovresti postare un po' di codice per rendere l'idea, perché così a prima vista non è chiaro dove sia il problema.

    Certo, se è il metodo di gestione dell'evento DoWork ad essere stato reso ricorsivo, allora capisco bene la problematica; in caso contrario, il DoWork dovrebbe semplicemente invocare la funzione che si occupa di portare avanti l'elaborazione, che può essere iterativa o ricorsiva senza nessun problema particolare, o almeno non capisco come possa ostacolarne il funzionamento.

    Per questo forse conviene che tu riporti una idea del codice scritto.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Homepage | Blog | Delphi Podcast | Altri link...

  3. #3
    Utente di HTML.it L'avatar di Veronica80
    Registrato dal
    May 2006
    Messaggi
    2,029
    Ciao Alka!
    Ti riporto un po di codice così da spiegarmi meglio (tenendo conto che possa aver sbagliato tutto però ).


    Questa è una normale funzione ricorsiva che userei per scansionare le cartelle/sottocartelle:

    codice:
       Private Sub ricorsione(ByVal _myFld As IO.DirectoryInfo)
            For Each subF As IO.DirectoryInfo In _myFld.GetDirectories
                ricorsione(subF)
            Next
            For Each f As IO.FileInfo In _myFld.GetFiles
               'agisco e manipolo i miei files
            Next
    
        End Sub
    richiamando la funzione e passando come argomento l'oggetto directoryInfo iniziale scansiona tutti file nelle sottocartelle.

    Io ho provato a richiamare tale funzione nel doWork del BGW:

    codice:
    Private Sub myBGW_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles myBGW.DoWork
            If myBGW.CancellationPending Then
                e.Cancel = True
            Else
                ricorsione(New IO.DirectoryInfo("C:\MiaCartella"))
            End If
    End Sub
    E per iniziare il processo chiamo uno start asincrono del BGW:

    codice:
    myBGW.RunWorkerAsync()
    Ora...così il codice viene eseguito ma non riesco a passare il "progresso" del lavoro all'evento ProgressChanged non avendo spazio di manovra sulla funzione (come farei se il loop fosse inserito nel DoWork stesso).

    Di conseguenza non riesco ad avere il risultato che voglio (ovvero in fase di scanning avere l'aggiornamento in una label o txtbox).

    Non so se sono stata chiara sul problema...ho sempre problemi a spiegarmi

  4. #4
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    23,887
    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    Ora...così il codice viene eseguito ma non riesco a passare il "progresso" del lavoro all'evento ProgressChanged non avendo spazio di manovra sulla funzione (come farei se il loop fosse inserito nel DoWork stesso).
    Per comunicare il progresso al worker, devi in qualche modo passare un riferimento al BackgroundWorker nella chiamata della tua funzione ricorsiva, aggiungendo un parametro di questo tipo, affinché la chiamata passi (opzionalmente) il valore anche alle chiamate ricorsive e in modo che la chiamata di primo livello ed eventualmente anche le seguenti possano accedere all'oggetto e comunicare in qualche modo il loro progresso, tenendo presente che ciascuna chiamata ha la visibilità del livello di ricorsività a cui è giunto (in breve, conosce solo il punto del lavoro in cui è arrivata per ciò che le compete), a meno di non passare alla funzione ricorsivamente anche altri parametri che permettano di avere un quadro complessivo del lavoro e di restituire così un "progresso" reale.

    Sintentizzando in due parole, la tua funzione ricorsiva deve essere "worker friendly": se vuoi visualizzare un progresso dell'elaborazione, la funzione deve consentire di passare un parametro (che può essere il BackgroundWorker, o anche una interface più generica fatta da te) affinché essa possa comunicare informazioni sull'avanzamento dei lavori; in caso contrario, la tua chiamata alla funzione è "atomica" e a nulla serve sapere che si tratta di una funzione ricorsiva: il risultato finale lo otterrai all'uscita della prima chiamata.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Homepage | Blog | Delphi Podcast | Altri link...

  5. #5
    Utente di HTML.it L'avatar di Veronica80
    Registrato dal
    May 2006
    Messaggi
    2,029
    Ok! Credo di aver capito!

    Ho modificato la mia sub in questo modo (passando il BGW come argomento):

    codice:
       Private Sub ricorsione(ByVal _myFld As IO.DirectoryInfo, byVal mioBGW as backgroundworker)
            For Each subF As IO.DirectoryInfo In _myFld.GetDirectories
                ricorsione(subF)
            Next
            For Each f As IO.FileInfo In _myFld.GetFiles
               'Qui eseguo la comunicazione di progresso
               mioBGW.ReportProgress(miaPerc, f.name)
    
            Next
    
        End Sub
    una volta eseguito il reportProgress() intercetto l'evento ProgressChanged e gestisto il dato passato come userState.

    Però riscontro un problema (che forse non dipende dal BGW) ovvero:

    Se uso una label dove visualizzo ogni volta il nome del file e basta funziona.
    codice:
    miaLbl.text=e.userState
    Se invece voglio creare un elenco in tempo reale mentre scansiono si blocca tutto come se il processo non fosse asincrono:
    codice:
    miaLbl.text &= string.concat(e.userstate,environment.newLine)
    è un limite delle label/txtBox?!?

    O sto continuando io a sbagliare?

  6. #6
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    23,887
    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    Ho modificato la mia sub in questo modo (passando il BGW come argomento) [...]
    Forse è un refuso, però mi sembra che tu non abbia poi passato il riferimento al BGW anche alla chiamata ricorsiva interna alla funzione.

    codice:
            For Each subF As IO.DirectoryInfo In _myFld.GetDirectories
                ricorsione(subF)
            Next
    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    Però riscontro un problema (che forse non dipende dal BGW) ovvero:
    Se invece voglio creare un elenco in tempo reale mentre scansiono si blocca tutto come se il processo non fosse asincrono:
    codice:
    miaLbl.text &= string.concat(e.userstate,environment.newLine)
    è un limite delle label/txtBox?!?
    O sto continuando io a sbagliare?
    Secondo me, il problema risiede nel fatto che stai usando un controllo che non è "multi riga", quindi vedi solo la prima mentre le altre, pur venendo aggiunte al testo, escono dall'area visibile del controllo e quindi non sono visibili.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Homepage | Blog | Delphi Podcast | Altri link...

  7. #7
    Utente di HTML.it L'avatar di Veronica80
    Registrato dal
    May 2006
    Messaggi
    2,029
    Quote Originariamente inviata da alka Visualizza il messaggio
    Forse è un refuso, però mi sembra che tu non abbia poi passato il riferimento al BGW anche alla chiamata ricorsiva interna alla funzione.

    codice:
            For Each subF As IO.DirectoryInfo In _myFld.GetDirectories
                ricorsione(subF)
            Next
    Non l'ho passato perchè ho l'oggetto sul mio form e punto a quello essendo accessibile.

    Quote Originariamente inviata da alka Visualizza il messaggio
    Secondo me, il problema risiede nel fatto che stai usando un controllo che non è "multi riga", quindi vedi solo la prima mentre le altre, pur venendo aggiunte al testo, escono dall'area visibile del controllo e quindi non sono visibili.

    Ciao!
    ahahah Alka ok che sono scarsa ma non fino a questo punto!

    Il controllo è multiline e non vedo solo la prima riga ma semplicemente si freezza tutto finchè il processo non è completato (come se non usassi una procedura asincrona) usando controlli multiline dove "appendo" nuovo testo.

    Se invece risetto il testo senza "appenderlo" funziona bene!

  8. #8
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    23,887
    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    Non l'ho passato perchè ho l'oggetto sul mio form e punto a quello essendo accessibile.
    A questo punto, non è chiaro perché passarlo come parametro la prima volta, per lo stesso motivo.

    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    ahahah Alka ok che sono scarsa ma non fino a questo punto!
    Credimi, in tanti anni di attività mi capitano "sviste" ben peggiori.

    Quote Originariamente inviata da Veronica80 Visualizza il messaggio
    Il controllo è multiline e non vedo solo la prima riga ma semplicemente si freezza tutto finchè il processo non è completato (come se non usassi una procedura asincrona) usando controlli multiline dove "appendo" nuovo testo.
    Se invece risetto il testo senza "appenderlo" funziona bene!
    Metti un breakpoint e verifica qual è il valore del controllo man mano che accodi le nuove stringhe per accertarti che vengano effettivamente accodate così come ti aspetti.

    Se pare che tutto funzioni, prova a inserire un valore di test sui controlli in fase di progettazione per verificare che non sia presente qualcos'altro che blocca la visualizzazione dei valori.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Homepage | Blog | Delphi Podcast | Altri link...

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2020 vBulletin Solutions, Inc. All rights reserved.