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

martedì 04 marzo 2008 - 11.18

Dave83 Profilo | Newbie

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?

totti240282 Profilo | Guru

Devi usare i delegate per poter modificare dei valori nel thread principale (UI)
C'è solo un capitano !!!!!!

aiedail92 Profilo | Expert

Ciao

Quello che devi fare è impostare la proprietà Value di una ProgressBar da un thread diverso dal suo giusto?

Per fare ciò devi usare il metodo Invoke passando come argomento il delegato che modifica la proprietà e il nuovo valore, più o meno in questo modo:

Private Delegate Sub ChangeValueHandler(ByVal newValue As Integer) Sub ChangeValue(ByVal newValue As Integer) ProgressBar1.Value = newValue End Sub Sub SubChiamanteDaThreadDiverso() '... ProgressBar1.Invoke(New ChangeValueHandler(AddressOf ChangeValue), ValoreDellaProgressBar) '... End Sub

Luca

Dave83 Profilo | Newbie

Vi ringrazio a entrambi, sono riuscito usando semplicemente una delegate.

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

Essendo che nel thread devo solo incrementare di uno la progress bar non ho passato alcun valore e dal thread richiamo la IncPB, a quanto pare funziona anche senza l'uso della invoke

Luca dici che posso lasciarlo così o che con l'uso della invoke da un altra sub sarebbe meglio dal punto di vista della sicurezza?


aiedail92 Profilo | Expert

Ciao

Va benissimo anche così, anzi, questa è la prima strada che avevo preso io. Comunque l'Invoke l'hai usata: BeginInvoke ha la stessa funzione di Invoke, solo viene eseguita in modo asincrono.

Luca

Dave83 Profilo | Newbie

Ok, grazie di tutto ;)

Ciao!

aiedail92 Profilo | Expert

Prego, di nulla.

Se non hai bisogno di altro, accetta una risposta, così segnaliamo il thread come concluso.

Alla prossima

Luca

Dave83 Profilo | Newbie

Un altro problema.
Come faccio a capire quando tutto il pool di thread è terminato (per chiudere ad esempio una connessione che uso nei thread)?

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 :(

aiedail92 Profilo | Expert

Ciao

Non credo di poterti aiutare, comunque forse è meglio aprire un nuovo thread, stiamo andando fuori argomento, e magari un thread vuoto richiama di più di uno con nove messaggi

Luca
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2024
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5