I wouldn't roll my own ObservableCollection for this. I'd just perform the .Add call on the UI thread.
public void test()
{
for (var i = 0; i < 10000; i++)
{
// create object
var animal = new Animal {Name = "test" + i};
// invoke list.Add on the UI thread
this.Dispatcher.Invoke(new Action(() => list.Add(animal)));
// sleep
System.Threading.Thread.Sleep(1);
}
}
Note that since you're in a Window subclass, this.Dispatcher
will correspond to the dispatcher for the UI thread. If you move this logic to, say, a model or view model class, you'll need to explicitly capture the value of Dispatcher.Current
on the UI thread, and pass that dispatcher manually to the background thread.
EDIT: OP asked for more information on using the Dispatcher outside of a FrameworkElement class. Here's how you would do that. The dispatcher for the UI thread is acquired on the UI thread by calling Dispatcher.CurrentDispatcher
. That dispatcher is then passed directly into the background thread procedure.
public class MainWindowViewModel
{
// this should be called on the UI thread
public void Start()
{
// get the dispatcher for the UI thread
var uiDispatcher = Dispatcher.CurrentDispatcher;
// start the background thread and pass it the UI thread dispatcher
Task.Factory.StartNew(() => BackgroundThreadProc(uiDispatcher));
}
// this is called on the background thread
public void BackgroundThreadProc(Dispatcher uiDispatcher)
{
for (var i = 0; i < 10000; i++)
{
// create object
var animal = new Animal { Name = "test" + i };
// invoke list.Add on the UI thread
uiDispatcher.Invoke(new Action(() => list.Add(animal)));
// sleep
System.Threading.Thread.Sleep(1);
}
}
}