为了使WPF UI响应,可以通过将密集型计算外包出UI来完成。最终,代码更改为:
for (int i = 2; i < 20; i++)
{
var t = Task.Factory.StartNew(() =>
{
var result = SumRootN(i);
this.Dispatcher.BeginInvoke(new Action(() =>
textBlock1.Text += "root " + i.ToString() + " " +
result.ToString() + Environment.NewLine)
,null);
});
}
更新:将密集型计算移出UI线程。
以下是来自Part1 article的引文来到此代码段:
为了从那些单独的任务线程输出到WPF UI(或者为了避免InvalidOperationException,它说“调用线程无法访问此对象,因为另一个线程拥有它。”)Dispatcher.BeginInvoke()被使用。
同一系列"Parallel Programming: Task Schedulers and Synchronization Context"的第2部分讲述了相同的代码片段(在引入本地迭代变量的小改动之后):
“这个需要更彻底的重构。我不能全部运行 UI线程上的任务,因为它们执行长时间运行的操作 这将使我的UI冻结。此外,它将取消所有 并行化的好处,因为只有一个UI线程。
我能做的就是将每项任务分成......“
the part1-article与the part2-article不矛盾吗?
将未在UI线程上运行的任务拆分为多个部分的需求是什么?
我在这里有什么不足之处?
答案 0 :(得分:4)
我认为这里有两个不同的概念。第1部分讨论如何在任务中运行代码以阻止UI线程。第2部分讨论并行运行多个任务。一个用于“不阻止UI线程”,另一个用于并行完成更多事情。如果你只有两个线程:UI线程和任务线程,那么事情并不是并行发生的,你没有利用并行处理的真正力量。
答案 1 :(得分:0)
这些陈述并不矛盾,它们相当于一个整体
UI线程负责刷新窗口及其中的控件,因此当您激活它们时会做出反应,使用鼠标光标等来检查它们。
如果你要执行一个长时间运行的操作,例如for-loop
10000次迭代,UI would freeze
并且变得没有响应(窗口将模糊,并且会出现小蓝色的死亡环节)。 for-loop
完成后,您的用户界面将再次出现。
为了减轻UI线程的额外负担,可以将长时间运行的任务放在单独的线程/任务中,以便它们同时执行。您的UI
将保持响应并接受命令(点击,按键,...)。
也许是无关紧要但正在努力解决它背后的基础知识
用户希望应用在计算时保持响应, 无论机器类型如何。 对于不同的应用程序,这意味着不同 对于一些人来说,这意味着提供更真实的物理, 更快地从磁盘或网络加载数据,快速呈现复杂的场景和在页面之间导航,找到方向 捕捉或快速处理数据。 无论计算类型如何,用户都希望他们的应用程序根据其输入进行操作,并消除其显示为暂停的实例 而它“思考。”
在此处阅读this文章。