WPF 性能工具显示 UI 线程何时锁定以及锁定多长时间

问题描述 投票:0回答:3

我确定它已经存在,但一直无法找到它。 我正在寻找一个在我的应用程序上显示某种动画的 WPF 控件,以便我可以轻松判断 UI 线程何时锁定。 我正在寻找一个控件来显示 UI 线程被锁定的时间。 这将是一个开发工具,我只会在调试模式下运行时启用,并且当 UI 长时间无响应时,将用于识别应用程序中的性能问题。 所以我正在寻找类似于 Visual Studio PerfWatson Monitor

我知道我可以自己写一个,但我确信其他人已经这样做了(而且可能比我更好)。如果您知道,请与我分享。谢谢!

c# wpf performance-testing ui-thread
3个回答
2
投票

我昨天打算回复这个问题,但没有完整的解决方案,只是一个建议!

我做了类似的事情,并创建了一个订阅 CompositionTarget.Rendering 的控件作为“UI 线程繁忙度”的简单指示器,然后在每秒更新一次的非常小的条形图上绘制帧速率(1.0/事件之间的时间)。所讨论的条形图非常轻量级,并且使用位图而不是 WPF 元素,因此它不会占用太多 CPU 时间。该控件可以作为装饰器覆盖在任何 WPF 表单上,以调试性能问题。

enter image description here

这非常有启发性,因为它实时显示 UI 线程丢失。

抱歉,我无法分享任何代码,因为它是我公司的专有代码,但我认为它可以让您了解如何解决这个问题。


0
投票

为仅包含旋转矩形的任何控件创建一个控件模板。

然后,当您处于调试模式时,从代码后面添加控件,以确保它不会进入发布状态。

#if DEBUG
if(runtimeCondition)
{
    //add or unhide control
}
#end if

真的很容易实现,这里有一个模板。

<ControlTemplate x:Key="spinningSquareTemplate">
            <ControlTemplate.Resources>
                <Storyboard x:Key="OnLoaded1" RepeatBehavior="Forever">
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)" Storyboard.TargetName="rectangle">
                        <EasingDoubleKeyFrame KeyTime="0:0:1" Value="360"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </ControlTemplate.Resources>
            <Rectangle x:Name="rectangle" Fill="#FFFFB900" Stroke="Black" RenderTransformOrigin="0.5,0.5">
                <Rectangle.RenderTransform>
                    <TransformGroup>
                        <ScaleTransform/>
                        <SkewTransform/>
                        <RotateTransform/>
                        <TranslateTransform/>
                    </TransformGroup>
                </Rectangle.RenderTransform>
            </Rectangle>
            <ControlTemplate.Triggers>
                <EventTrigger RoutedEvent="FrameworkElement.Loaded">
                    <BeginStoryboard Storyboard="{StaticResource OnLoaded1}"/>
                </EventTrigger>
            </ControlTemplate.Triggers>

        </ControlTemplate>

当您的 UI 锁定时,方块将停止旋转。


0
投票

这是基于 Dr. 的基本解决方案。安德鲁对 CompositionTarget.Rendering

见解

using System.Threading;

//...
public class UiMonitor
{
    public int FPS => _fps;

    private int _frames;
    private int _fps;
    private readonly Timer _timer;

    public UiMonitor()
    {
        _timer = new Timer(HandleTick, null, 1000, 1000);

        Application.Current.Dispatcher.BeginInvoke(() =>
        {
            CompositionTarget.Rendering += HandleCompositionRendering;
        });
    }

    private void HandleTick(object state)
    {
        _fps = Interlocked.Exchange(ref _frames, 0);
    }

    private void HandleCompositionRendering(object sender, EventArgs e)
    {
        Interlocked.Increment(ref _frames);

        if (_fps > 30)
        {
            // ...
        }
    }
}

如果您想创建类似的控件,只需从

INotifyPropertyChanged
继承,然后在 FPS 更新后向您设计的任何图表或指标发出通知(FPS 属性已经每秒更新一次)。

© www.soinside.com 2019 - 2024. All rights reserved.