为什么要拆分未在UI线程上运行的任务,以使WPF应用程序更具响应性?

时间:2013-04-02 10:53:53

标签: c# wpf multithreading c#-4.0 task-parallel-library

part1 "Getting Started"

  • Alexandra Rusina的系列。 .NET Framework 4中的并行编程

为了使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的引文来到此代码段:

  • “为了使UI响应,我将使用任务,这是由任务并行库引入的新概念。任务表示通常在单独的线程上运行的异步操作”
  • “编译,运行......好吧,用户界面是响应式的”

为了从那些单独的任务线程输出到WPF UI(或者为了避免InvalidOperationException,它说“调用线程无法访问此对象,因为另一个线程拥有它。”)Dispatcher.BeginInvoke()被使用。

同一系列"Parallel Programming: Task Schedulers and Synchronization Context"的第2部分讲述了相同的代码片段(在引入本地迭代变量的小改动之后):

  

“这个需要更彻底的重构。我不能全部运行   UI线程上的任务,因为它们执行长时间运行的操作   这将使我的UI冻结。此外,它将取消所有   并行化的好处,因为只有一个UI线程。

     

我能做的就是将每项任务分成......“

the part1-articlethe part2-article不矛盾吗?

将未在UI线程上运行的任务拆分为多个部分的需求是什么?

我在这里有什么不足之处?

2 个答案:

答案 0 :(得分:4)

我认为这里有两个不同的概念。第1部分讨论如何在任务中运行代码以阻止UI线程。第2部分讨论并行运行多个任务。一个用于“不阻止UI线程”,另一个用于并行完成更多事情。如果你只有两个线程:UI线程和任务线程,那么事情并不是并行发生的,你没有利用并行处理的真正力量。

答案 1 :(得分:0)

这些陈述并不矛盾,它们相当于一个整体 UI线程负责刷新窗口及其中的控件,因此当您激活它们时会做出反应,使用鼠标光标等来检查它们。 如果你要执行一个长时间运行的操作,例如for-loop 10000次迭代,UI would freeze并且变得没有响应(窗口将模糊,并且会出现小蓝色的死亡环节)。 for-loop完成后,您的用户界面将再次出现。
为了减轻UI线程的额外负担,可以将长时间运行的任务放在单独的线程/任务中,以便它们同时执行。您的UI将保持响应并接受命令(点击,按键,...)。 也许是无关紧要但正在努力解决它背后的基础知识

  

用户希望应用在计算时保持响应,   无论机器类型如何。       对于不同的应用程序,这意味着不同       对于一些人来说,这意味着提供更真实的物理,       更快地从磁盘或网络加载数据,快速呈现复杂的场景和在页面之间导航,找到方向   捕捉或快速处理数据。       无论计算类型如何,用户都希望他们的应用程序根据其输入进行操作,并消除其显示为暂停的实例   而它“思考。”

在此处阅读this文章。