In my WPF project, when it first opens, there is a great deal of initialisation/loading to perform.
I do this within an opening dialog and because of the time taken for the load the process is initialised as follows:
Task.Factory.StartNew(() =>
{
DoLoad();
});
The DoLoad method periodically calls a delegate to update the screen to indicate progress. The loading process involves creatings several objects that themselves create collections (some Observable collections for data binding) etc and this process works fine.
However.
Once the loading is complete, any attempt to modify these collections is greeted with the exception:
"This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread."
If I move the loading process into the main thread , i.e. just calling DoLoad, everything is fine but the interface is frozen until the loading is complete. The length of time it takes to load means that this is not acceptable.
So how do I maintain a responsive UI while loading. I thought that moving the loading into a separate thread and using delegates to update the UI is EXACTLY what you're supposed to do?
I found the following code snippet which I thought would solve my problem:
Where do I get a thread-safe CollectionView?
public class MTObservableCollection<T> : ObservableCollection<T>
{
public override event NotifyCollectionChangedEventHandler CollectionChanged;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
NotifyCollectionChangedEventHandler CollectionChanged = this.CollectionChanged;
if (CollectionChanged != null)
foreach (NotifyCollectionChangedEventHandler nh in CollectionChanged.GetInvocationList())
{
DispatcherObject dispObj = nh.Target as DispatcherObject;
if (dispObj != null)
{
Dispatcher dispatcher = dispObj.Dispatcher;
if (dispatcher != null && !dispatcher.CheckAccess())
{
dispatcher.BeginInvoke(
(Action)(() => nh.Invoke(this,
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset))),
DispatcherPriority.DataBind);
continue;
}
}
nh.Invoke(this, e);
}
}
}
All my collections now derive from this, but it has made no difference whatsoever.
Thanks for any help.