Visualizzazione dei risultati da 1 a 7 su 7
  1. #1
    Utente di HTML.it
    Registrato dal
    Aug 2002
    Messaggi
    281

    [VB.NET 2005] Modificare una form da un thread separato

    Ho realizzato una piccola applicazione che fa una scansione di un range di IP locale e che fornisce in ouput dei risultati (per ora su un file di testo). In questa applicazione ho messo una progressbar in modo da capire quando manca al termine della scansione.
    Il problema è che questa scansione la faccio in multithread, in modo da non dover aspettare la risposta del primo IP per interrogare il secondo.

    Quindi uso il metodo ThreadPool.QueueUserWorkItem per richiamare il metodo (contenuto in una classe) che mi farà la scansione del singolo IP. Il problema è che poi non riesco ad aggiornare il valore della progressbar dal metodo, in quanto nel framework2 è stato aggiunto un controllo che in fase di debug segnala queste operazioni come errori, ma in realtà se sì lancia il file .exe a parte il tutto funziona perfettamente. Come posso ovviare a questo problema?
    In rete ho letto di usare l'oggetto BackgroundWorker, ma in realtà questo oggetto non lavora in multithread, in quanto gli ip vengono scansionati uno alla volta e il tutto risulta molto più lento.


    Qualcuno ha un'altra soluzione?

  2. #2
    Amaro C++, il gusto pieno dell'undefined behavior.

  3. #3
    Mi sono imbattuto in un problema simile in un applicativo che ho sviluppato e ho risolto in questo modo:
    codice:
    delegate void SetControlValueCallback(Control oControl, string propName, object propValue);
    
    private void SetControlPropertyValue(Control oControl, string propName, object propValue)
    {
           try
           {
               if (oControl.InvokeRequired)
               {
                    SetControlValueCallback d = new SetControlValueCallback(SetControlPropertyValue);
                    oControl.Invoke(d, new object[] { oControl, propName, propValue });
                }
                else
                {
                     Type t = oControl.GetType();
                     System.Reflection.PropertyInfo[] props = t.GetProperties();
                     foreach(System.Reflection.PropertyInfo p in props)
                     {
                         if(p.Name.ToLower() == propName.ToLower())
                         {
                                p.SetValue(oControl,propValue,null);
                         }
                      }
                  }
             }
             catch(Exception e)
             {
                        //Gestione errori
             }
    }
    Nel thread che gestisce la progress bar:
    codice:
    SetControlPropertyValue(prbAvanzamento,"Value", index);
    dove prbAvanzamento è il controllo che vuoi modificare,
    value è la proprietà da modificare,
    index è il valore da attribuire alla progress

    Ovviamente il codice funziona su qualsiasi controllo

  4. #4
    Utente di HTML.it
    Registrato dal
    Aug 2002
    Messaggi
    281
    Grazie a entrambi, sono riuscito a risolvere il problema con l'uso della delegate

    Grazie anche del tuo codice zero85, così in effetti come metodo è molto più versatile

    edit: solo una cosa non capisco
    Perchè nell'ultimo if il valore viene impostato a NULL?

    p.SetValue(oControl,propValue,null);

  5. #5
    Utente di HTML.it
    Registrato dal
    Aug 2002
    Messaggi
    281
    Ah un'altra cosa

    Io lancio i thread con questo metodo

    codice:
    ThreadPool.QueueUserWorkItem(AddressOf nmd.main, Me)
    quindi passo al metodo main della classe nmd il form o l'oggetto da cui viene richiamata

    E poi nel main della classe nmd faccio
    so.SetControlPropertyValue(so.ProgressBar1, "Value", so.ProgressBar1.Value + 1)

    Solo che certe volte la barra non arriva fino in fondo, si ferma leggermente prima, anche se in realtà l'operazione è stata eseguita perfettamente. Questo perchè a volte la barra non fa in tempo ad aggiornarsi prima che il thread successivo la incrementi. C'è qualche modo in cui posso ovviare a questa cosa usando il tuo metodo?

    Con quello che avevo fatto io funzionava perfettamente, ma era un metodo molto più semplice e adattato all'uso specifico che ne dovevo fare.
    codice:
        Private Delegate Sub IncPBDelegate()
    
        Public Sub IncPB()
            If Me.InvokeRequired() Then
                Me.BeginInvoke(New IncPBDelegate(AddressOf IncPB))
                Return
            End If
    
            ProgressBar1.Value += 1
        End Sub
    Come vedi non passa nessun valore, non fa altro che incrementare di 1 il value della progressbar

  6. #6
    Utente di HTML.it
    Registrato dal
    Aug 2002
    Messaggi
    281
    Un altro problema.
    Come faccio a capire quando tutto il pool di thread è terminato?

    Tra l'altro mi serve fare questa cosa sotto forma di servizio (ovviamente non ci sarà più la progressbar) e nei servizi a quanto pare i metodi invoke e simili non ci sono

  7. #7
    Be', nel servizio, proprio perché la progressbar non ci sarà, non si porrà nemmeno il problema.
    Amaro C++, il gusto pieno dell'undefined behavior.

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 © 2024 vBulletin Solutions, Inc. All rights reserved.