如何在应用程序中诊断UI线程上的挂起?

时间:2011-10-11 20:52:24

标签: wpf performance rendering

我正在构建一个WPF桌面应用程序,其UI虽然动态,但在我看来并不像它应该特别苛刻。此应用程序中的典型用户控件实现了一个包含两列网格的扩展器,其中一列包含标签,另一列包含文本框或组合框。扩展器内容的XAML如下所示:

<DockPanel Style="{StaticResource Style_ExpandedGridRowView}"
           Focusable="False">
    <DockPanel.Resources>
        <DataTemplate DataType="{x:Type vm:BooleanFieldViewModel}">
            <local:GridBooleanField DataContext="{Binding}" />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:ChoiceFieldViewModel}">
            <local:GridChoiceField DataContext="{Binding}" />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:CodeLookupFieldSingleSelectionViewModel}">
            <local:GridCodeLookupField DataContext="{Binding}" />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:CodeLookupFieldMultipleSelectionViewModel}">
            <local:GridCodeLookupMultiSelectField DataContext="{Binding}"/>
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:CurrencyFieldViewModel}">
            <local:GridCurrencyField DataContext="{Binding}" />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:DateFieldViewModel}">
            <local:GridDateField DataContext="{Binding}" />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:NotesFieldViewModel}">
            <local:GridNotesField DataContext="{Binding}" />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:NumberFieldViewModel}">
            <local:GridNumberField DataContext="{Binding}" />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:TextFieldViewModel}">
            <local:GridTextField DataContext="{Binding}" />
        </DataTemplate>
        <DataTemplate DataType="{x:Type vm:TimeFieldViewModel}">
            <local:GridTimeField DataContext="{Binding}" />
        </DataTemplate>
    </DockPanel.Resources>
    <AdornerDecorator>
        <ItemsControl ItemsSource="{Binding Fields, Mode=Default}"
                      Focusable="False">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Vertical"
                                Grid.IsSharedSizeScope="True" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </AdornerDecorator>
</DockPanel>

我已经分析了我的视图模型,枚举Fields属性所需的时间少于100个,其中包含的项目少于15个。

当我展开它时,扩展器渲染其内容时,它会采用 20-30秒的顺序。

在此期间,应用程序完全没有响应。这将被写入输出窗口,每4-5秒写一条消息:

The thread '<No Name>' (0x21b0) has exited with code 0 (0x0).
The thread '<No Name>' (0x1c54) has exited with code 0 (0x0).
The thread '<No Name>' (0x1c7c) has exited with code 0 (0x0).
The thread '<No Name>' (0x2638) has exited with code 0 (0x0).
The thread '<No Name>' (0x1bf0) has exited with code 0 (0x0).

一旦内容最终呈现,我可以打开和关闭扩展器,没有任何可察觉的延迟。

无论是使用调试还是发布版本,以及我是在IDE中还是在桌面上运行,都会出现延迟。

我尝试构建针对不同版本的.NET框架,但无济于事。

我推测这里发生的是渲染线程中的某种死锁。我的意思是,我想不出任何方式在2GHz上运行指令的CPU可能花费30秒来确定如何在屏幕上排列30个矩形。但我无法看到任何可以控制的方式。

如何诊断此问题的原因?而且,当然,修复它?正如您可能想象的那样,如果我无法修复它,那么这就是一个项目查杀错误。

修改

我应该补充一点,我尝试过的一件事是无效,是按照here所述禁用硬件加速。这没有可察觉的效果。我也试过使用参考光栅化器,只是它太慢了,我甚至无法让我的应用程序开始挂起。

1 个答案:

答案 0 :(得分:0)

ItemsControl中有多少件商品?您是否尝试在VirtualizingStackPanel中使用ItemsPanelTemplate