none
请教关于ScrollViewer中使用大量项时候的性能 RRS feed

  • 问题

  • 不单止ScrollViewer,ListBox这些,只要是有可滚动的,如果里面有大量控件项的话,会很卡很慢。不知道有什么办法。
    2010年11月20日 7:50

答案

  • 你好,

    你可以尝试WPF在.NET框架4.0中增加的新特性BitmapCache. 它可以把元素以位图的形式进行缓存。更多信息请参见http://msdn.microsoft.com/zh-cn/library/system.windows.media.bitmapcache.aspx

    如果仍然无法达到理想的效果,我们建议你提升硬件水平来改善你应用程序的表现。

    Best regards,

    Min


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    • 已标记为答案 野老 2010年11月29日 9:04
    2010年11月26日 8:58
    版主

全部回复

  • 看了一下,只要拖动滚动条,CPU使用率立刻上去了。

    不知道这有什么好办法。

     

    2010年11月22日 2:32
  • 你好,

    你可以使用接口虚拟化(UI Virtualization)来优化此时的性能。在不使用接口虚拟化时,所有的控件,无论是否可见,都会被创建到可视化树中区。 当可视化树中包含大量元素的时候,将会消耗大量的内存与CPU。WPF提供了VirtualizingStackPanel(通过 VirtualizingPanel 提供的功能)计算可见项,并与来自 ItemsControl(如 ListBoxListView)的 ItemContainerGenerator 协同工作,以便仅为可见项创建元素。

    你可以通过设置ListBox的VirtualizingStackPanel.IsVirtualizing附加属性来应用接口虚拟化。

    更多的信息请参见http://msdn.microsoft.com/zh-cn/library/bb613565.aspx#User_Interface_Virtualization

    希望这对你有帮助。

     

    Best regards,

    Min Zhu


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    • 已建议为答案 Jie BaoModerator 2010年11月22日 4:52
    • 取消建议作为答案 野老 2010年11月22日 5:15
    2010年11月22日 3:40
    版主
  • 这个我试过了,只有在创建的时候会比较快。但是在操作的时候,也就是在拖动滚动条的时候,仍然是无比慢。CPU使用率飙升。

    这个问题应该怎么解决呢?

    补充一下,VirtualizingStackPanel的话,是只对绑定的有效,对吧。

    现在工程里面的并没有使用数据绑定,而是生成了每一项再追加进去。这样的话,和StackPanel就没什么区别了。

    而且,需要在里面进行布局,所以,很是烦恼。

    2010年11月22日 4:54
  • 你好,

    一般来说,在拖动滚动条时的性能时的CPU使用都会在可以接受的范围内。 如果方便的话,请问你能否创建一个简单的演示项目来重现这个问题,并上传该项目到SkyDrive上http://explore.live.com/windows-live-skydrive。 这将对我们更准确与快速地找到产生问题的原因非常有帮助。同时,我想了解一下你的CPU/显卡配置,操作系统版本与VS版本。

    谢谢!

    Min Zhu


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    2010年11月22日 6:43
    版主
  • 谢谢回复

    我弄不清楚中文的WPF论坛和英文的有什么区别……然后我在那边贴了代码。很简单的一段代码。

    这样的一段可能不能很准确的描述我的工程。但是基本上就像这样。

    CPU Atom N270 1.6G

    内存 512

    显卡 945集成

    VS版本是08

    操作系统版本是xp Embedded 标准版

    <Window x:Class="LotsOf.MainWindow"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Title="MainWindow" Height="300" Width="300"
      Loaded="Window_Loaded">
     <Grid>
      <ListBox x:Name="HelloKitty">
       <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
         <VirtualizingStackPanel></VirtualizingStackPanel>
        </ItemsPanelTemplate>
       </ListBox.ItemsPanel>
       <ListBox.ItemTemplate>
        <DataTemplate>
         <TextBlock Text="{Binding}" FontFamily="{Binding}"/>
        </DataTemplate>
       </ListBox.ItemTemplate>
      </ListBox>
     </Grid>
    </Window>
    
    using System.Windows;
    using System.Windows.Media;
    
    namespace LotsOf
    {
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
      public MainWindow()
      {
       InitializeComponent();
      }
    
      private void Window_Loaded(object sender, RoutedEventArgs e)
      {
       HelloKitty.ItemsSource = Fonts.SystemFontFamilies;
      }
     }
    }

    2010年11月22日 7:47
  • 你好,

    我运行了你的代码,并且能够重现你的问题。

    在重现时我发现,在这段代码中,性能问题并不是由CPU引起的。LISTBOX在滚动时由于需要对所有控件进行重新布局,会消耗大量的CPU计算,但是更大的一个问题是在这段代码中使用了大量不同的字体。由于使用了接口虚拟化,不可见的字体会被卸载,重新可见时会被重新加载。大量的对字体的加载/卸载导致了性能问题。

    由于系统字体的总数并不是太多,我建议你可以禁用接口虚拟化来解决这个问题。这样所有的字体都会在控件加载时被正确地引用,而不需要反复读取。

    希望这对你有帮助。

    Best regards,

    Min


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    2010年11月23日 1:47
    版主
  • 谢谢回复。

    我贴的代码只是一个例子吧,就像一开始的时候问的问题一样,

    ScrollView,ListBox这些在滚动的时候是不是都会消耗大量CPU来运算内部控件布局?

    因为实际工程中,我的需求是这样的,

    在ScrollView中,套一个WrapPanel,在WrapPanel中,再进行3个一行的若干行布局。

    这样在行数多的时候,在运行的时候CPU使用率基本上都会达到100%。

    有什么好的办法能够降低资源的消耗。下面是我大概的布局。

    我尝试用Canvas来取代Grid,用性能工具来测试,得到的反馈是相差无几。

    由于我的运行环境显卡是集成显卡,DX版本是9,我看了一下WPF的硬件支持,只是1.

    不知道是不是这个缘故,使得在滚动ScrollView的时候,会特别慢,并且内容的背景图,

    如同没有装显卡驱动的效果一样,波浪的推进。

     

    =====================================================

    <ScrollViewer>

    <WrapPanel>

    <Box/><Box/><Box/>

    <Box/><Box/><Box/>

    <Box/><Box/><Box/>

    <Box/><Box/><Box/>

    </WrapPanel>

    </ScrollViewer>

    里面的Box内容如下。

    <Box>

    <Grid>

    <Grid.Background>

    <ImageBrush/>

    </Grid.Background>

    <TextBlock/>

    <Rectangle/>

    <Rectangle/>

    <Rectangle/>

    </Grid>

    <Box>

    2010年11月23日 15:50
  • 你好,

    由于布局发生了变化,在每一小次的滚动中,所有ScrollViewer在可视化树中的子元素都会进行重新布局的运算。

    在配置相对较低的机器上,对于可视化树较为复杂的ScrollViewer,我建议把ScrollViewer.IsDeferredScrollingEnabled属性设为True以提高性能。

    在T1下,由于只有部分图形功能使用了硬件加速,相对于T2,会需要更多的CPU运算。

    Min

     

     


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    2010年11月24日 3:34
    版主
  • IsDeferredScrollingEnabled也设置了,这个属性的意思是拖动结束之后发生ValueChanged事件吧?

    如果是这样的话,ScrollViewer就失去了原本的意义。

    那么,为什么不换作分页来处理。

    请问,如何才能够判断当前的瓶颈是因为CPU,内存,还是显卡呢?

    因为机器的配置本来就很不好,一台老旧的上网本。

    2010年11月24日 7:28
  • 你好,

    由于你观察到CPU使用频繁达到100%,可以说CPU的处理能力遇到了瓶颈。

    你可以使用Windows SDK提供的WPF性能分析工具(WPF Performance Suite)来得到更为详细的信息。

    更多关于WPF性能分析工具的信息请参见http://msdn.microsoft.com/zh-cn/library/aa969767.aspx

    Best regards,

    Min


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    2010年11月25日 6:34
    版主
  • 这个我也做了,

    在ScrollViewer使用的时候,只是单纯的一个UserControl,上面没有追加任何控件,帧数在59左右。

    当上面有布局,Grid和Canvas分别降8到6帧,如果上面再追加Rectangle3个和TextBox一个,降到大概40多左右。

    请问这算是正常水平吗?也就是说,不管怎么样优化,只有提升硬件水平了。

    还是说可以使用别的办法来使得软件使用的时候有明显性能提升。

    2010年11月25日 6:44
  • 你好,

    你可以尝试WPF在.NET框架4.0中增加的新特性BitmapCache. 它可以把元素以位图的形式进行缓存。更多信息请参见http://msdn.microsoft.com/zh-cn/library/system.windows.media.bitmapcache.aspx

    如果仍然无法达到理想的效果,我们建议你提升硬件水平来改善你应用程序的表现。

    Best regards,

    Min


    Please remember to click “Mark as Answer” on the post that helps you, and to click “Unmark as Answer” if a marked post does not actually answer your question. This can be beneficial to other community members reading the thread.
    • 已标记为答案 野老 2010年11月29日 9:04
    2010年11月26日 8:58
    版主
  • 看来最后一个方法对我来说也有难度了。 因为目标环境是3.5 sp1,要上4.0就得重新烧机器了。 不过对于自己来说,倒是可以值得尝试的。 谢谢了。
    2010年11月26日 16:39
  • 最后的最后,3.5SP1我终于放弃了,直接一张图片都能杀死那台机器。

    试了一下4.0,工作的不错。很好,那只好去建议升级net版本了。

    谢谢回复帮助我的各位。

    2010年11月29日 9:02