自定义绘制控件的糟糕性能

2024-02-29

我正在做简单的图形控制wpf。我无法解释也无法解决性能问题:与 winform 相比,它太慢了。也许我做错了什么。

我准备了demo来演示这个问题。

这是测试控制:

public class Graph : FrameworkElement
{
    private Point _mouse;
    private Point _offset = new Point(500, 500);

    public Graph()
    {
        Loaded += Graph_Loaded;
    }

    private void Graph_Loaded(object sender, RoutedEventArgs e)
    {
        // use parent container with background to receive mouse events too
        var parent = VisualTreeHelper.GetParent(this) as FrameworkElement;
        if (parent != null)
            parent.MouseMove += (s, a) => OnMouseMove(a);
    }

    protected override void OnRender(DrawingContext context)
    {
        // designer bugfix
        if (DesignerProperties.GetIsInDesignMode(this))
            return;

        Stopwatch watch = new Stopwatch();
        watch.Start();

        // generate some big figure (try to vary that 2000!)
        var radius = 1.0;
        var figures = new List<LineSegment>();
        for (int i = 0; i < 2000; i++, radius += 0.1)
        {
            var segment = new LineSegment(new Point(radius * Math.Sin(i) + _offset.X, radius * Math.Cos(i) + _offset.Y), true);
            segment.Freeze();
            figures.Add(segment);
        }
        var geometry = new PathGeometry(new[] { new PathFigure(figures[0].Point, figures, false) });
        geometry.Freeze();
        var pen = new Pen(Brushes.Black, 5);
        pen.Freeze();
        context.DrawGeometry(null, pen, geometry);

        // measure time
        var time = watch.ElapsedMilliseconds;
        Dispatcher.InvokeAsync(() =>
        {
            Window.GetWindow(this).Title = string.Format("{0:000}ms; {1:000}ms", time, watch.ElapsedMilliseconds);
        }, DispatcherPriority.Loaded);
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        var mouse = e.GetPosition(this);
        if (e.LeftButton == MouseButtonState.Pressed)
        {
            // change graph location
            _offset.X += mouse.X - _mouse.X;
            _offset.Y += mouse.Y - _mouse.Y;
            InvalidateVisual();
        }
        // remember last mouse position
        _mouse = mouse;
    }
}

下面是在 xaml 中使用它的方法:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfApplication1"
        Title="MainWindow" Height="350" Width="525" WindowState="Maximized">
    <Grid Background="White">
        <local:Graph/>
    </Grid>
</Window>

备注:控件会绘制图形,可以用鼠标移动图形:

它将在标题中显示 2 个测量值:第一个是花费了多长时间OnRender()完成,第二个是实际渲染花费的时间(渲染后第一次调用)。

尝试改变这一点2000: 环境1000 makes moving舒服的,3000就像在重新绘制图形之前有半秒的延迟(在我的电脑上)。

问题:

  1. 好用吗InvalidateVisual()更新图形偏移量MouseMove?如果不好,什么是正确的无效技术?
  2. 冻结,有很多,没有任何明显的效果。我是否需要使用它们?
  3. 看起来只需要5ms完成渲染,但主观移动需要更长的时间(200ms+)。这是为什么?

主要问题当然是性能,为什么这么糟糕?我可以在 winform 控件中绘制几十万行,直到它变得像我的 wpf 控件只用 1000 行一样草率... =(


我找到了最后一个问题的答案。使用鼠标移动时,渲染时间的测量无法正常工作。但是如果调整窗口大小,那么第二次就会变成300ms(在我的电脑上2000人物)。所以这不是一个鼠标错误无效(第一个问题),但是渲染确实很慢。


WPF 不太擅长这种任务。我指的是一般矢量图形。感谢保留模式。它对于控件渲染很有用,但对于经常更新的繁忙图形则不那么适用。我在尝试在 WPF 地图上渲染 GPS 轨迹时遇到了同样的问题。

我建议使用 direct2d 并将其托管在 WPF 中。像这样的东西:http://www.codeproject.com/Articles/113991/Using-Direct-D-with-WPF http://www.codeproject.com/Articles/113991/Using-Direct-D-with-WPF

这将为您带来高性能。

PS 别误会我的意思。 WPF 没有什么不好的。它旨在解决特定问题。编写控件并构建令人印象深刻的 UI 非常容易。我们认为自动布局系统的很多东西是理所当然的。但它不可能在所有可能的情况下都很聪明,微软也没有很好地解释这些情况,在这些情况下它不是一个好的选择。让我举一个例子。 iPad 具有高性能,因为它具有固定分辨率和绝对布局。如果您修复 WPF 窗口大小并使用画布面板,您将获得相同的体验。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自定义绘制控件的糟糕性能 的相关文章

  • 获取按下的按钮的返回值

    我有一个在特定事件中弹出的表单 它从数组中提取按钮并将标签值设置为特定值 因此 如果您要按下或单击此按钮 该函数应返回标签值 我怎样才能做到这一点 我如何知道点击了哪个按钮 此时代码返回 DialogResult 但我想从函数返回 Tag
  • 如何避免情绪低落?

    我有一个实现状态模式每个状态处理从事件队列获取的事件 根据State因此类有一个纯虚方法void handleEvent const Event 事件继承基础Event类 但每个事件都包含其可以是不同类型的数据 例如 int string
  • 指针问题(仅在发布版本中)

    不确定如何描述这一点 但我在这里 由于某种原因 当尝试创建我的游戏的发布版本进行测试时 它的敌人创建方面不起作用 Enemies e level1 3 e level1 0 Enemies sdlLib 500 2 3 128 250 32
  • C - 找到极限之间的所有友好数字

    首先是定义 一对友好的数字由两个不同的整数组成 其中 第一个整数的除数之和等于第二个整数 并且 第二个整数的除数之和等于第一个整数 完美数是等于其自身约数之和的数 我想做的是制作一个程序 询问用户一个下限和一个上限 然后向他 她提供这两个限
  • Json.NET - 反序列化接口属性引发错误“类型是接口或抽象类,无法实例化”

    我有一个类 其属性是接口 public class Foo public int Number get set public ISomething Thing get set 尝试反序列化Foo使用 Json NET 的类给我一条错误消息
  • 如果使用 SingleOrDefault() 并在数字列表中搜索不在列表中的数字,如何返回 null?

    使用查询正数列表时SingleOrDefault 当在列表中找不到数字时 如何返回 null 或像 1 这样的自定义值 而不是类型的默认值 在本例中为 0 你可以使用 var first theIntegers Cast
  • WPF TabControl,用C#代码更改TabItem的背景颜色

    嗨 我认为这是一个初学者的问题 我搜索了所有相关问题 但所有这些都由 xaml 回答 但是 我需要的是后台代码 我有一个 TabControl 我需要设置其项目的背景颜色 我需要在选择 取消选择和悬停时为项目设置不同的颜色 非常感谢你的帮助
  • Qt moc 在头文件中实现?

    是否可以告诉 Qt MOC 我想声明该类并在单个文件中实现它 而不是将它们拆分为 h 和 cpp 文件 如果要在 cpp 文件中声明并实现 QObject 子类 则必须手动包含 moc 文件 例如 文件main cpp struct Sub
  • Web API - 访问 DbContext 类中的 HttpContext

    在我的 C Web API 应用程序中 我添加了CreatedDate and CreatedBy所有表中的列 现在 每当在任何表中添加新记录时 我想填充这些列 为此目的我已经覆盖SaveChanges and SaveChangesAsy
  • 指针减法混乱

    当我们从另一个指针中减去一个指针时 差值不等于它们相距多少字节 而是等于它们相距多少个整数 如果指向整数 为什么这样 这个想法是你指向内存块 06 07 08 09 10 11 mem 18 24 17 53 7 14 data 如果你有i
  • for循环中计数器变量的范围是多少?

    我在 Visual Studio 2008 中收到以下错误 Error 1 A local variable named i cannot be declared in this scope because it would give a
  • 从库中捕获主线程 SynchronizationContext 或 Dispatcher

    我有一个 C 库 希望能够将工作发送 发布到 主 ui 线程 如果存在 该库可供以下人员使用 一个winforms应用程序 本机应用程序 带 UI 控制台应用程序 没有 UI 在库中 我想在初始化期间捕获一些东西 Synchronizati
  • 如何在 VBA 中声明接受 XlfOper (LPXLOPER) 类型参数的函数?

    我在之前的回答里发现了问题 https stackoverflow com q 19325258 159684一种无需注册即可调用 C xll 中定义的函数的方法 我之前使用 XLW 提供的注册基础结构 并且使用 XlfOper 类型在 V
  • 实体框架 4 DB 优先依赖注入?

    我更喜欢创建自己的数据库 设置索引 唯一约束等 使用 edmx 实体框架设计器 从数据库生成域模型是轻而易举的事 现在我有兴趣使用依赖注入来设置一些存储库 我查看了 StackOverflow 上的一些文章和帖子 似乎重点关注代码优先方法
  • C++ 复制初始化和直接初始化,奇怪的情况

    在继续阅读本文之前 请阅读在 C 中 复制初始化和直接初始化之间有区别吗 https stackoverflow com questions 1051379 is there a difference in c between copy i
  • 如何使我的表单标题栏遵循 Windows 深色主题?

    我已经下载了Windows 10更新包括黑暗主题 文件资源管理器等都是深色主题 但是当我创建自己的 C 表单应用程序时 标题栏是亮白色的 如何使我自己的桌面应用程序遵循我在 Windows 中设置的深色主题 你需要调用DwmSetWindo
  • Process.Start 阻塞

    我正在调用 Process Start 但它会阻止当前线程 pInfo new ProcessStartInfo C Windows notepad exe Start process mProcess new Process mProce
  • const、span 和迭代器的问题

    我尝试编写一个按索引迭代容器的迭代器 AIt and a const It两者都允许更改容器的内容 AConst it and a const Const it两者都禁止更改容器的内容 之后 我尝试写一个span
  • ASP.NET MVC 6 (ASP.NET 5) 中的 Application_PreSendRequestHeaders 和 Application_BeginRequest

    如何在 ASP NET 5 MVC6 中使用这些方法 在 MVC5 中 我在 Global asax 中使用了它 现在呢 也许是入门班 protected void Application PreSendRequestHeaders obj
  • 使用 libcurl 检查 SFTP 站点上是否存在文件

    我使用 C 和 libcurl 进行 SFTP FTPS 传输 在上传文件之前 我需要检查文件是否存在而不实际下载它 如果该文件不存在 我会遇到以下问题 set up curlhandle for the public private ke

随机推荐

  • 场景测试是连续单元测试的组吗?

    我读了维基百科 http en wikipedia org wiki Scenario testing关于场景测试的文章 但我很遗憾地说它很短 我想知道 场景测试是连续单元测试的集合吗 或者 也许像单个多步骤单元测试 许多框架是否支持场景测
  • 如何使用 java 中的 swing 在 jeditorpane 中的超链接上添加悬停效果

    使用jEditorPane 中的超链接 https stackoverflow com questions 3693543 hyperlink in jeditorpane链接 我设法在 jEditorPane 中获取超链接 但现在我想为超
  • 开发过程中样式未应用于 vue web 组件

    在开发 Vue Web 组件时 style不应用于Web组件 而是添加到head该文件的 这意味着样式在影子 DOM 中被忽略 以下是我在 main js 中包装 Web 组件的方法 import Vue from vue import w
  • Multer 和快速验证器在验证中造成问题

    我正在提交带有图像的表格 使用下面的代码 router post upload upload image single categoryLogo categoryRules categoryCreationRules validate ca
  • 引用外部对象的 JavaScript 作用域

    基本上 我使用一个名为的元类框架Joose http joose it对于 Javascript 它允许我使用更优雅的类语法 但我不知道如何从类声明的更深层次方法中引用对象的范围 我还使用 require js 进行依赖管理 这是一个类定义
  • jQuery自动上下滚动div

    我写了一个fiddle http jsfiddle net f7e3d440 8 自动上下滚动 div 效果很好 但是向下滚动时存在问题 它不显示最后一行 在本例中为 String4 有人可以帮我解决这个问题吗 div class cont
  • 在 ASP.Net 中运行时按名称隐藏 GridView 列

    是否可以在运行时按名称显示 隐藏 GridView 列 我可以通过索引来做到这一点 如下所示 gridReviews Columns 4 Visible false 不过我想执行以下操作 gridReviews Columns Name V
  • Terraform:如何读取地图列表?

    请参阅下面的示例 data aws kms secrets api key count length keys var keys secret name secret name payload element values var keys
  • 显式保存与隐式保存 - 什么时候更喜欢什么?

    我目前正在开发一个 wp7 应用程序 不想透露太多 但我在用户交互方面遇到了一些困难 我不确定的主要问题是 我应该在对话框中提供显式保存按钮并使用手机后退按钮作为取消 还是应该隐式保存用户点击手机后退按钮的时间 我想得越多 我就越不确定什么
  • 如何在 Scala JLine 调用之间保存和加载历史记录

    我在用着Scala JLine http search maven org artifactdetails 7Corg scala lang virtualized 7Cjline 7C2 10 2 RC1 7Cjar在我的 CLI 程序中
  • MySQL 5.5 至 5.7 停止使用索引

    我有 Magento 1 9 2 1 并在Apache2和MySQL 5 5上成功运行 我尝试将其迁移到另一台服务器并使用 NGINX 和 MySQL 5 7 但网站开始变得非常慢 12 秒对 2 秒 经过几个小时的调试 我发现一个查询有问
  • 简单的 PHP 联系表格未发送[关闭]

    这个问题不太可能对任何未来的访客有帮助 它只与一个较小的地理区域 一个特定的时间点或一个非常狭窄的情况相关 通常不适用于全世界的互联网受众 为了帮助使这个问题更广泛地适用 访问帮助中心 help reopen questions 发完更多帖
  • 如何在Steam WebAPI中通过AppName获取steam AppID

    所以我试图通过输入游戏名称来启动蒸汽游戏 为此我问自己是否可以通过输入的名称找出steam App ID 所以我尝试通过我的 steamApps 文件夹收集 ID 但没有成功 我还找到了一个网站 您可以在其中搜索特定游戏的名称 例如 htt
  • 期间发生内部错误:“更新 Maven 项目

    当我转换为 Maven 项目时 错误是 gt An internal error occurred during Updating Maven Project gt Unsupported IClasspathEntry kind 4 有什
  • 使用 Ajax 下载 JQuery 文件

    当我的用户选择生成报告时 我使用 John Culviner 出色的 fileDownload 插件来生成 请稍候 消息 当用户单击链接时 我向 PHP 发送一个 ajax 请求 该请求在服务器上生成 PDF 此时 我正在尝试更新 file
  • 调用未定义的函数curl_init(),即使它在php7中启用

    我刚刚在我的 Ubuntu 上安装了 php7 起初 没有任何问题 我的网站可以运行 但突然间 它开始返回 Call to undefined function curl init 错误 现在 我的页面包含的curl代码不起作用 在 php
  • 在 SwiftUI 3.0 iOS 15 中调整视图与键盘显示

    我的注册页面有VStack嵌入一 个ScrollView嵌入在VStack 在最里面VStack我有一系列TextField与定制TextFieldStyle 注册页面的 UI 如下所示 VStack ScrollView VStack s
  • Azure Powershell Linux

    除了 Linux Azure Powershell 之外 是否还有更多适用于 Linux Azure Powershell 的 cmdlet 是否有 Azure Powershell 的官方存储库对于Linux 有没有办法让终端在启动时启动
  • android 中的 vimeo 视频为 .mp4 格式

    我想在我的 Android 应用程序中播放 vimeo 视频 要播放我需要 mp4 格式的视频 我在下面的链接中有用户将视频获取为 mp4 格式 当我在浏览器中点击此网址时 它会要求我将文件另存为 mp4 格式 但是当我尝试通过编码获得相同
  • 自定义绘制控件的糟糕性能

    我正在做简单的图形控制wpf 我无法解释也无法解决性能问题 与 winform 相比 它太慢了 也许我做错了什么 我准备了demo来演示这个问题 这是测试控制 public class Graph FrameworkElement priv