Consider the unit test below :
[TestMethod]
public void MVCE()
{
asyncMethodNoCollectionView().Wait(); // Does not fail
asyncMethodWithCollectionView().Wait(); // Fails
}
private async Task asyncMethodNoCollectionView()
{
var collection = new ObservableCollection<string>();
await Task.Run(() =>
{
Task.Delay(4000).Wait();
});
collection.Add("hello");
}
private async Task asyncMethodWithCollectionView()
{
var collection = new ObservableCollection<string>();
var view = CollectionViewSource.GetDefaultView(collection);
await Task.Run(() =>
{
Task.Delay(4000).Wait();
});
collection.Add("hello");
}
For some obscure reason I cannot figure out, calling CollectionViewSource.GetDefaultView(collection);
will make the .Add("Hello")
line in the second method fail, returning a :
System.NotSupportedException : This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.
And this behaviour is consistent (I ran the test dozens of times, on separate machines, with different workload).
My understanding is that the exception is thrown because the Thread resuming the await
in the 1st method is the one that created the ObservableCollection
. Whereas in the 2nd method, the resuming Thread is not the one that created the collection. Hence, it fails because this collection must be edited on the original Thread.
Why would calling CollectionViewSource.GetDefaultView cause the resuming thread to systematically be different from the originating one ?
(This question is somehow linked, but it is not clear to me how it answers mine. )