Before you flag my question as being a duplicate, hear me out.
Most people have a long running non-UI operation that they are doing and need to unblock the UI thread. I have a long running UI operation which must run on the UI thread which is blocking the rest of my application. Basically, I am dynamically constructing DependencyObjects at run time and adding them to a UI component on my WPF application. The number of DependencyObjects that need to be created depends upon user input, of which there is no limit. One of the test inputs I have has about 6000 DependencyObjects that need to be created and loading them takes a couple minutes.
The usual solution of using a background worker in this case does not work, because once the DependencyObjects are created by the background worker, they can no longer be added to the UI component since they were created on the background thread.
My current attempt at a solution is to run the loop in a background thread, dispatch to the UI thread for each unit of work and then calling Thread.Yield() to give the UI thread a chance to update. This almost works - the UI thread does get the chance to update itself a couple times during the operation, but the application is still essentially blocked.
How can I get my application to keep updating the UI and processing events on other forms during this long running operation?
EDIT: As requested, an example of my current 'solution':
private void InitializeForm(List<NonDependencyObject> myCollection)
{
Action<NonDependencyObject> doWork = (nonDepObj) =>
{
var dependencyObject = CreateDependencyObject(nonDepObj);
UiComponent.Add(dependencyObject);
// Set up some binding on each dependencyObject and update progress bar
...
};
Action background = () =>
{
foreach (var nonDependencyObject in myCollection)
{
if (nonDependencyObject.NeedsToBeAdded())
{
Dispatcher.Invoke(doWork, nonDependencyObject);
Thread.Yield(); //Doesn't give UI enough time to update
}
}
};
background.BeginInvoke(background.EndInvoke, null);
}
Changing Thread.Yield() to Thread.Sleep(1) seems to work, but is that really a good solution?