即使使用后台线程,WinRT XAML UI也会停止

时间:2015-03-17 16:48:27

标签: c# multithreading winrt-xaml

我有一个应用程序,其中不可能快速完成的活动在后台线程上运行。例如,我有一些项目要显示我开始显示通用图标的位置,而背景代码试图查看是否存在应该显示的关联图像。

当XAML尝试获取图像时,如果我还没有获取图像,我将查询添加到队列中以供稍后处理并暂时返回null。队列处理基本上是这样做的:

  • 获取互斥锁(以便我可以安全地操作单个项目)
  • 如果该项目尚未加入队列,请添加
  • 如果队列尚未运行,请启动它
  • 释放互斥锁

使用以下命令运行队列:

objectFileQueueRunning = true;
cts = new CancellationTokenSource();
Task.Run(() => ProcessObjectFileQueue(cts.Token));

队列代码基本上继续从列表中取出顶部项目并对其进行处理,直到我们用完项目或取消令牌设置为止。在队列代码中使用相同的互斥锁,但仅限于从列表中删除顶部项目以及将objectFileQueueRunning重置为false时。

我的问题是UI线程基本上没有响应,直到队列代码完成运行...即使它在后台线程上运行。

我已经对正在执行的应用程序运行了性能分析,但无法发现任何似乎给我任何关于要查看的内容的提示。

我是否需要暂停后台线程以使UI线程有机会与用户交互?是不是我在运行后台线程这么紧,以至于UI线程没有看到它?

1 个答案:

答案 0 :(得分:1)

在我的情况下,解决方案原来是使用StackPanel作为ItemsPanelTemplate与后台线程相结合做了很多工作。

使用StackPanel的问题在于它会导致虚拟化被禁用,这意味着所有元素都可以一次创建。

切换到ItemsWrapGrid允许GridView使用虚拟化,因此只创建可见或即将可见的元素。反过来,这会导致后台工作量减少。

我使用StackPanel的原因可追溯到我的应用程序首次为Windows 8.0编写时。当用户水平滚动时,使用默认设置会导致问题,因为滚动条的大小会有所不同。这似乎已在Windows 8.1中得到修复,但我没有想过在我更新应用程序时重新访问XAML。

如果其他人遇到类似问题,则共享。