Прежде чем вы ставите мой вопрос как дубликат, выслушайте меня.
У большинства людей есть длительная работа, отличная от UI, которую они выполняют, и нужно разблокировать поток пользовательского интерфейса. У меня длинная работа UI, которая должна запускаться в потоке пользовательского интерфейса, который блокирует остальную часть моего приложения. В принципе, я динамически строю DependencyObject
во время выполнения и добавляю их к компоненту пользовательского интерфейса в своем приложении WPF. Количество DependencyObject
, которое необходимо создать, зависит от пользовательского ввода, которого нет предела. Один из тестовых входов, которые у меня есть, составляет около 6000 DependencyObject
, которые необходимо создать, и загрузка их занимает пару минут.
Обычное решение использования фонового работника в этом случае не работает, поскольку после того, как DependencyObject
создаются фоновым рабочим, они больше не могут быть добавлены в компонент пользовательского интерфейса, поскольку они были созданы в фоновом потоке.
Моя текущая попытка решения - запустить цикл в фоновом потоке, отправить в поток пользовательского интерфейса для каждой единицы работы, а затем вызвать Thread.Yield()
, чтобы дать потоку пользовательского интерфейса возможность обновиться. Это почти работает - поток пользовательского интерфейса получает возможность обновить себя пару раз во время операции, но приложение по-прежнему по-прежнему заблокировано.
Как я могу заставить приложение продолжать обновлять пользовательский интерфейс и обрабатывать события в других формах во время этой длительной операции?
EDIT: В соответствии с запросом, пример моего текущего "решения":
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);
}
Изменение Thread.Yield()
до Thread.Sleep(1)
похоже на работу, но действительно ли это хорошее решение?