2010-08-04 3 views
5

Sto cercando di utilizzare un worker in background per recuperare una grande quantità di dati dal database senza arrestare il thread principale. Questo sembra funzionare bene, tranne che quando si tratta di aggiornare l'interfaccia utente, l'aggiornamento blocca lo schermo. Codice rilevante come segue:C# Aggiornamento dell'interfaccia utente Worker di background

private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    {    
     lvwTest.BeginUpdate(); 
     lvwTest.Items.Clear(); 

     // Populate the UI 
     foreach (TestItem ti in testData) 
     { 
      ListViewItem lvi = lvwTest.Items.Add(ti.Value1); 
      lvi.SubItems.Add(ti.Value2); 
     } 

     lvwTest.EndUpdate();      
    } 

L'aggiornamento richiede circa 2 - 3 secondi, per cui lo schermo è bloccato. Mi rendo conto che solo il thread principale può aggiornare lo schermo, ma è possibile caricare questi dati in memoria in qualche modo (in un thread in background o in un'altra istanza di list list o qualcosa del genere) e quindi visualizzarli? Tutto quello che voglio succedere è che il programma aggiorni semplicemente i dati senza occupare tempo nel thread principale.

risposta

1

vi consiglio caricamento dei dati in memoria e utilizzando una modalità virtuale ListView. In questo modo, crei solo gli oggetti ListViewItem quando necessario.

1

Se devi caricare una quantità enorme di dati nell'interfaccia utente, richiederà tempo e bloccherà la nostra app. L'opzione è scorrimento o impaginazione intelligente. Carichi tutti i dati ma li metti pezzo per pezzo su richiesta dell'utente.

0

Oltre alla virtualizzazione, suggerirei di suddividere gli articoli in lotti di, ad esempio, 100 e aggiungendo ogni batch nel proprio messaggio. In questo modo, l'interfaccia utente ha una modifica per elaborare altri messaggi mentre i batch vengono aggiunti allo ListView.

In altre parole, tutto il gestore RunWorkerCompleted esegue la coda del primo batch per l'aggiunta in un messaggio separato. Il metodo di aggiunta aggiungerà quindi gli elementi e quindi accoderà il batch successivo. Questo continuerà fino a quando non ci saranno più elementi da aggiungere. A quel punto, riattiverai la parte pertinente della tua interfaccia utente (ListView).

0

Poiché la maggior parte di quanto sopra è un buon consiglio, ma in realtà non risolve il problema immediato, ecco un altro approccio: Questo aggiornerà la GUI e la manterrà reattiva. Supponendo che tu sia nell'app WinForm?

 Application.DoEvents(); 
     this.Refresh(); 

Tuttavia, questo non vuol dire che forse non si dovrebbe ascoltare le idee dall'alto :-)

+0

Si tratta di un'applicazione WinForm - ma nei giorni VB6, DoEvents è stato visto di buon occhio perché potrebbe cambia la sequenza di eventi. Non è questo il caso di C#? –

+0

Potresti avere ragione, è ancora un po 'un trucco da quello che ho sentito. Dipende dalla complessità della tua app. Ho riscritto la mia ultima semplice app in WPF, che in realtà è davvero un bel Quadro. – Remy