Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#, MVVM, Tasks and the UI Thread

We have an application built according to the MVVM pattern. At various times we kick off tasks to go to a database to retrieve data, we then populate an ObservableCollection to which a WPF control is bound with that data.

We are a little confused, when we populate the ObservableCollection we are doing so on the task thread, not the UI thread, yet the UI is still updated/behaving correctly. We were expecting an error and to have to change the code to populate the collection on the UI thread.

Is this a dangerous scenario and should we populate on the UI thread anyway?

Code to get data:

Task.Factory.StartNew(() =>
    UiDataProvider.RefreshForwardContractReport(fcrIdField.Value)
)
.ContinueWith(task => {
    if (task.Result.OperationSuccess)
    {
        // This updates the ObseravableCollection, should it be run on UI thread??
        RefreshReport(task.Result.OperationResult);
    }
});
like image 314
Chris Avatar asked Jan 30 '14 10:01

Chris


1 Answers

WPF keeps allowing more cross-thread operations with each release. Other MVVM platforms do not allow them at all. In the case of ObservableCollection, unless you are using EnableCollectionSynchronization, updating from a background thread is incorrect.

I agree with @avo in that you should treat your ViewModel (your logical UI) as though it had UI thread affinity (like the literal UI). All data binding updates should be done in the UI context.

As @Cameron pointed out, this is most easily done via async:

var result = await Task.Run(
    () => UiDataProvider.RefreshForwardContractReport(fcrIdField.Value));
if (result.OperationSuccess)
{
  RefreshReport(result.OperationResult);
}
like image 58
Stephen Cleary Avatar answered Sep 22 '22 16:09

Stephen Cleary