This post explains how to process data from a task in WPF in a way I’d consider “best-practice”. The main code could or should be in the view-model.
Code-behind (keep it short or better yet use a delegate command)
private void Button_Click(object sender, RoutedEventArgs e) { try { // Get some parameters if necessary [...] this.SomeViewModelData.StartSearch([parameters...]); } catch (Exception ex) { log.Warn("Error handling...", ex); } }
And the code in the view-model:
- StartSearch() is a method in the view-model class and sets the properties of the view-model that are bound to the UI
- this.IsWaiting is some bool property to indicate the waiting status in the UI
- this.ResultData is not bound but contains data to be processed
- ProcessResultData() processes the result and sets the output (for example it might fill an ObservableCollection)
public void StartSearch([parameters...]) { try { var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); this.IsWaiting = true; Task.Factory.StartNew(() => { this.ResultData = DatabaseService.GetComplexData([parameters...]); }).ContinueWith((t) => { // Invoke in UI Thread via scheduler this.ProcessResultData(); // Cancel waiting indicator this.IsWaiting = false; }, uiScheduler // <-- This is the important part: Continue // the task in the UI thread { if (t.Exception != null) { log.Warn("Task exception handling...", t.Exception); } this.IsWaiting = false; }, TaskContinuationOptions.OnlyOnFaulted); } catch (Exception ex) { log.Warn("Do exception handling... ", ex); this.IsWaiting = false; } }