在将我的问题标记为重复项之前,请听我说。如何在长时间运行* UI *操作期间刷新UI
大多数人都有一个长时间运行的非UI操作,他们正在做,并需要解锁UI线程。我有一个长时间运行的UI操作,其中必须在阻塞我的应用程序的其余部分的UI线程上运行。基本上,我在运行时动态构建DependencyObject
,并将它们添加到我的WPF应用程序的UI组件上。需要创建的DependencyObject
的数量取决于用户输入,其中没有限制。我有一个测试输入有大约6000 DependencyObject
需要创建并加载它们需要几分钟。
在这种情况下使用后台工作程序的常用解决方案不起作用,因为一旦DependencyObject
由后台工作程序创建,它们就不能再添加到UI组件,因为它们是在后台线程上创建的。
我目前的解决方案尝试是在后台线程中运行循环,为每个工作单元分配UI线程,然后调用Thread.Yield()
为UI线程提供更新机会。这几乎奏效 - UI线程在操作过程中确实有机会更新自己,但应用程序仍然被阻止。
如何让我的应用程序在这个长时间运行的操作过程中不断更新UI和处理其他窗体上的事件?
编辑: 按照要求,我目前的“解决方案”的一个例子:
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)
似乎工作,但真正好的解决办法?
发布您的代码的例子。 –
看来,主要问题是您需要创建的DependencyObjects的数量。在这种情况下,您可以尝试将创建分解为您在调度程序中排队的多个任务。只要单个DependencyObject的创建不是太长时间运行,就可以以块的形式处理它们,并保持UI的相应响应。 “如果我们将计算任务分解为可管理的块,我们可以定期返回调度程序并处理事件,我们可以给WPF一个重绘和处理输入的机会。” - http://msdn.microsoft.com/en-us/library/ms741870(v=vs.110).aspx – DavidN
'基本上,我在运行时动态构建DependencyObjects并将它们添加到我的WPF应用程序的UI组件' - 我一直在想如果你真的需要的是一个'ItemsControl'和一个合适的ViewModel。 –