Leggere un file di testo asincronamente ed aggiornare un textbox

venerdì 25 luglio 2008 - 13.46

intelinside Profilo | Newbie

Salve,

devo implementare un sistema per cui leggendo un file da disco questi viene mostrato in realtime in un form con textbox.

Ho creato una classe che tramite IEnumerable ed un thread mentre legge riga per riga il file richiama attraverso un delegato il metodo di aggiornamento del form che contiene il textbox che mostrerà il file.

Ovviamente accade che pur se in background la UI sembra 'bloccata' immagino perche la message pump di tutti gli invoke fatti dall'altro thread finiscono per bloccare comunque il form che contiene il textbox multiline.

Ora, potrei leggere tutto il file in background ed alla fine mostrarlo ma possibile che non esiste un modo per far aggiornare il textbox mentre si legge il file ?

(ad onor del vero mettendo un Threading.Thread.Sleep(100) nelle fasi cicliche di reperimento dati c'è un miglioramento ma comunque è inaccettabile)

Grazie dei consigli

Lanello Profilo | Senior Member

nella tua funzione di aggiornamento del textbox prova con un "banale"

Application.Doevents()



non è molto "stilosa" come soluzione, ma permette alla tua application di eseguire tutte le operazioni di ridisegno che ti permette di non avere quell'effetto "blocco" che stai verificando.

Facci sapere ;)
-----------------------------------------------------
La ricompensa per una cosa ben fatta, è averla fatta.

intelinside Profilo | Newbie

Si ho provato con Application.Doevents(), ma come dicevi non è la soluzione stilistica migliore.

Lo scenario è che ho una classe che attraverso questo metodo

Private Sub StartCollect()
Dim SB As New Text.StringBuilder(1000), localCounter As Integer
Do
SB.Append(DirectCast(InnerIEnumerableClass.GetEnumerator, IEnumerator(Of String)).Current & ControlChars.CrLf)
localCounter += 1
If localCounter >= LineBuffer Then
GuiDelegate(SB.ToString)
SB.Remove(0, SB.Length)
End If
Loop Until Not CType(InnerIEnumerableClass.GetEnumerator, IEnumerator).MoveNext
If SB.Length > 0 Then GuiDelegate(SB.ToString)
End Sub
End Class

richiamato da un thread invoca il delegato GUIDELEGATE ogni 100 righe lette (in effetti viene letta riga x riga nel MoveNext dell'interfaccia IEnumerator dell'oggetto InnerIEnumerableClass).

Nell'applicazion Winform che consuma questa classe avviene il marshaling:


Private Sub UIUpdateMethod(ByVal m As String)
If TextBox1.InvokeRequired Then
TextBox1.Invoke(New MultithreadReader.GUIUpdater(AddressOf UIUpdateMethod), m)
Else
TextBox1.Text &= m.ToString & ControlChars.CrLf
'Application.DoEvents()
End If
End Sub

Effettivamente mettendo il DoEvents() tutto fila liscio ma è corretto tutto ciò ? Non si dovrebbe evitare il DoEvents ?

Grazie per i consigli

Lanello Profilo | Senior Member

ho dato una rapida occhiata al tuo codice, ma lavori con files di testo o binari???

perchè mi pare che ti stai complicando un po la vita....

comunque a parte questo...

il comando

Application.DoEvents()

non è ERRATO, è soltanto uno strumento del .NET che indica alla tua Application di svuotare la coda delle istruzioni da eseguire, comprese quelle intrinseche di ridisegno delle interfacce.

quindi non è Errata, è solo poco "stilosa".

se te la fai da solo, facendo "girare" solo le operazioni che ti servono strettamente senza far svuotare la coda delle istruzioni all'applicazione riesci ad ottenere prestazioni migliori.

ma se il metodo ti risolve il problema senza grossi rallentamenti non vedo perchè "infognarsi" in un problema più grosso di te.

vedi http://msdn.microsoft.com/en-us/library/system.windows.forms.application.doevents.aspx per i riferimenti al metodo doevents.
-----------------------------------------------------
La ricompensa per una cosa ben fatta, è averla fatta.

intelinside Profilo | Newbie

Ciao grazie per le risposte.

Il mio codice è un codice di test, non un caso reale.
In pratica avevo progettatto una classe che definendo nel new un file di testo ed un buffer di righe da leggere questa avvolga all'interno un oggetto IEnumerable ed un IEnumerator(of String) in modo che si potesse ciclare le righe del file senza obbligatoriamente mettere tutto il contenuto in memoria.

Quindi nel movenext di IEnumerator legge la riga seguente e prospone in current la riga letta.

Nella classe principale c'è un metodo sincrono che espone l'enumeratore e c'è un metodo asincrono che tramite un thread cicla il file per ogni N righe richiamando l'invoke di un delegato che deve essere puntato ad una routine nel form o assembly ospitante la classe.

Inizialmente la routine che serviva il delegato era la scrittura dello stesso file in 'background' in una windows application poi nel test di visualizzazione mi sono dovuto fermare per il blocco della UI (che in caso di scrittura file invece non avveniva).

Comunque solo con Dovents() in effetti si ha un UI decentemente utilizzabile.

Grazie dei consigli
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-2023
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5