Based on previous answers like this and this, I know that scalar properties can be updated from a worker thread and the propertychanged event will be marshaled to the UI thread. I also know that collections must be manually marshalled or modified using the binding synchronization introduced in .NET 4.5. This has never really caused an issue for me until this afternoon. Consider this snippet:
private void OnDevicesUpdated(object sender, EventArgs args)
{
SelectedVehicleGroupInfos?.ForEach(g =>
{
var selectedDevice = g.SelectedDeviceSummary;
g.DeviceSummaries = new ObservableCollectionEx<DeviceSummary>(SelectedVehicle.ResolveSupportedDevices());
if (selectedDevice != null)
{
////g.SelectedDeviceSummary = g.DeviceSummaries.FirstOrDefault(d => d.Id.Equals(selectedDevice.Id));
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
g.SelectedDeviceSummary = g.DeviceSummaries.FirstOrDefault(d => d.Id.Equals(selectedDevice.Id))));
}
});
}
For context, I have a listbox of "Groups" on a view where the item template is also a listbox (of "DeviceSummary" objects). The method above is the elapsed handler for a Timer and therefore executed on a background thread.
Since I am completely replacing the bound collection of devices for each group, I need to store the currently selected device and reselect after the new list is built. The problem is the line inside the if statement. The SelectedItem property of the device listbox is bound to g.SelectedDeviceSummary and when I try to set that property from a background thread (See the commented out line), the UI fails to reselect the appropriate device. No exceptions. No anything.
However, when I manually marshall the setting of the bound property, everything works and my mind is turned upside down because I though updating scalar properties from non-ui threads was kosher. What gives?