2017-06-01 8 views
1

Ich habe eine ObservableCollection<Customer>() und zu Testzwecken habe ich einfache for-Schleife, die 2.000.000 Datensätze mit Zufallszahlen zu suchen. Wenn ich klicke, um die Kunden zu laden, zeigt dies einen netten Spinner und funktioniert gut.warten auf ListBox zu beenden Rendering WPF

private async void button_Click(object sender, RoutedEventArgs e) 
    { 

     bool result = DatabaseMaster.CheckConnection(con); 
     spinner.Visibility = Visibility.Visible; 
     spinner.Spin = true; 
     customers = await Task.Run(()=>DatabaseMaster.GetCustomers()); 
     customerListBox.ItemsSource = customers; 
     spinner.Visibility = Visibility.Collapsed; 
     spinner.Spin = false; 
    } 

Allerdings habe ich ein Textfeld für eine Suche verwendet und möchte die Kunden durchsuchen und die Ansicht aktualisieren. Ich habe versucht,

jedoch diese durch einen Fehler des aufrufenden Threads dieses Objekt nicht zugreifen, da ein anderer Thread es besitzt.

Ich versuche dies jedoch die UI springt immer noch als Aktualisierung der Artikelquelle. irgendwelche Ideen oder sollte ich mehr von inotifypropertychange lernen?

private async void search_TextChanged(object sender, TextChangedEventArgs e) 
    { 
     spinner.Visibility = Visibility.Visible; 
     spinner.Spin = true; 
     customerListBox.Background = Brushes.Gray; 
     customerListBox.IsEnabled = false; 
     await this.Dispatcher.BeginInvoke(new Action(() => 
     { 
      customerListBox.ItemsSource = customers.Where(X => X.name.ToLower().Contains(searchTextBox.Text.ToLower())); 
     }), null); 
     customerListBox.Background = Brushes.White; 
     customerListBox.IsEnabled = true; 
     spinner.Visibility = Visibility.Collapsed; 
     spinner.Spin = false; 
    } 
+0

die 'Where' im Hintergrund Sie in ui Thread zugewiesen werden Aufgabe und aktualisieren Sie nur die ItemsSource im ui thread. Es wird immer noch flackern, wenn es zu viele Einträge gibt. – NtFreX

+1

Beachten Sie, dass '.Where (...)' nicht wirklich viel tut. Wenn Sie in der Aufgabe müssen Sie '.Where (...). ToList()'. – grek40

+0

@ grek40 es aufrufen friert immer noch ein, wenn ich meine Textbox eintippe, denn wenn es einfriert, zeigt es nicht einmal meinen Spinner? – Bish25

Antwort

2

Es ist wie customers aussieht, ist nur eine lokale Sammlung. Normalerweise ist es wenig sinnvoll, sie in einem anderen Thread abzufragen. Stellen Sie jedoch sicher, dass UI-Objekte (customerListBox in Ihrem Beispiel) nur aus dem UI-Thread verwendet werden, wenn Sie es weiterhin möchten.

Wie

var text = searchTextBox.Text.ToLower(); 
var r = await Task.Run(() => customers.Where(X.name.ToLower().Contains(text).ToList()); 
customerListBox.ItemsSource = r; 
+0

Die Benutzeroberfläche friert immer noch ein, wenn ich das hinzufüge, es friert für etwa 4 Sekunden ein und reagiert dann. Ich glaube, es ist diese Zeile 'customerListBox.ItemsSource = r;' verursacht das Problem – Bish25

+0

@ bish25 Sie haben wahrscheinlich die erste Version ohne 'ToList()' versucht. Versuchen Sie die aktuelle –

+0

Wenn ich versuche, dass ich bekomme den Fehler "Der aufrufende Thread kann nicht auf dieses Objekt zugreifen, weil ein anderer Thread es besitzt." ' – Bish25

0

Wenn Sie Ihren Code ändern, um folgende sollte es funktionieren (weil ItemSource wird statt im Inneren der Aufgabe

customerListBox.ItemsSource = await Task.Run(()=> customers.Where(X => X.name.ToLower().Contains(searchTextBox.Text.ToLower()))); 
+0

es friert immer noch für etwa 3 Sekunden, es zeigt nicht sogar meine Spinner auf ui Thread, die mich glauben, dass die Benutzeroberfläche selbst verlangsamt es – Bish25

Verwandte Themen