So Im developing an addon with a UI that is used inside an application (main application). To make my UI responsive when the main application is working I'm starting my UI in its separate thread like this:
public void ShowDialog(IIFCConverter ifcConverter)
{
thread = new Thread(x =>
{
thread.Name = "UI-thread";
window = new MainWindow();
var mainViewModel = ServiceLocator.Current.GetInstance<MainWindowViewModel>();
mainViewModel.SetIFCConverter(x as IIFCConverter);
ViewModelLocator.MainWindow = window;
window.ShowDialog();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start(ifcConverter);
}
The first time I start my addon it all works. The second time I start it and it tries to raise events (like OnCollectionChanged) I get a NotSupportedException with the message: "This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread"
This is one of my methods:
private void AddNewFile(AddNewFileMessage obj)
{
if (!(obj.Sender is ButtonViewModel)) return;
if (string.IsNullOrEmpty(obj.Path)) return;
var ifcFileViewModel = new IFCFileViewModel(new Common.Model.IFCFile { Path = obj.Path, Active = true });
DispatcherHelper.CheckBeginInvokeOnUI(() =>
{
ListBoxItems.Insert(ListBoxItems.Count - 1, ifcFileViewModel);
});
}
I get this eventhough Im using the DispatcherHelper from MVVM light. I have tried using the "normal" dispatcher to, but that gives me the same result.
First of all Im curious to know the mechanics of why its doing this? I've checked my threads and I can see that the OnOllectionChanged is called from my UI-thread. I cant seem to find any differences to the thread structure between the first run (that works) and the following.
Second, what can I do about this?
Things that I've tested that didnt help:
- Im using the IoC container from MVVM light and its registered as a LocatorProvider, but I create a new IoC container everytime I initialize the UI and set that instance as the LocatorProvider.
- Im initializing the DispatcherHelper in the constructor of my window. So that should be on the correct thread.
Something that does actually work is wrapping the action in a try Catch-block like this:
private void AddNewFile(AddNewFileMessage obj) { if (!(obj.Sender is ButtonViewModel)) return; if (string.IsNullOrEmpty(obj.Path)) return; var ifcFileViewModel = new IFCFileViewModel(new Common.Model.IFCFile { Path = obj.Path, Active = true }); DispatcherHelper.CheckBeginInvokeOnUI(() => { try { ListBoxItems.Insert(ListBoxItems.Count - 1, ifcFileViewModel); } catch(Exception ex) { } });}
However I find this very ugly and would like to avoid it and why does that even work? Everything seems to work fine when I wrap all my actions in try Catch-blocks.

ViewModelis created by a thread that is not UI. Change that and your solution will work with either of the dispatchers. - XAMlMAXvar mainViewModel = ServiceLocator.Current.GetInstance<MainWindowViewModel>();is created inside theUI-Thread, that is different than the calling thread, so the object is owed by a different thread, how can you not see that? - XAMlMAX