【问题标题】:Reducing time in C# Forms Control.set_Text(string) function减少 C# Forms Control.set_Text(string) 函数的时间
【发布时间】:2010-04-25 22:07:51
【问题描述】:

希望快速回答​​(这似乎很适合)...

我刚刚在我的应用程序上使用 VS2010 进行了性能分析,结果发现我在 Control.set_Text(string) 函数上花费了大约 20% 的时间,因为我在我的很多地方更新标签应用程序。

窗口有一个计时器对象(表单计时器,而不是线程计时器),它有一个timer1_Tick 回调,它在每个滴答声中更新一个标签(以提供一种秒表的效果),并且每次更新大约 15 个标签第二个。

除了增加更新间隔之外,是否有人对如何减少更新表单上的文本所花费的时间提出快速建议?我应该使用其他结构或功能吗?

【问题讨论】:

    标签: c# winforms timer


    【解决方案1】:

    我自己也遇到了这个问题,最终创建了自己的简单 Label 控件。

    .Net 的 Label 控件非常复杂,因此比我们想要的要慢。

    你可以创建一个继承Control的类,在构造函数中调用SetStyle使其双缓冲和用户绘制,然后重写OnPaint方法调用e.Graphics.DrawString并绘制Text属性。
    最后,覆盖TextTextChanged 并调用Invalidate

    只要您不需要 AutoSize,这将比标准的 Label 控件快得多。

    这是我的实现:(目前在生产中使用)

    ///<summary>A simple but extremely fast control.</summary>
    ///<remarks>Believe it or not, a regular label isn't fast enough, even double-buffered.</remarks>
    class FastLabel : Control {
        public FastLabel() {
            SetStyle(ControlStyles.AllPaintingInWmPaint
                   | ControlStyles.CacheText
                   | ControlStyles.OptimizedDoubleBuffer
                   | ControlStyles.ResizeRedraw
                   | ControlStyles.UserPaint, true);
        }
        protected override void OnTextChanged(EventArgs e) { base.OnTextChanged(e); Invalidate(); }
        protected override void OnFontChanged(EventArgs e) { base.OnFontChanged(e); Invalidate(); }
    
        static readonly StringFormat format = new StringFormat {
            Alignment = StringAlignment.Center,
            LineAlignment = StringAlignment.Center
        };
        protected override void OnPaint(PaintEventArgs e) {
            e.Graphics.DrawString(Text, Font, SystemBrushes.ControlText, ClientRectangle, format);
        }
    }
    

    如果您不想居中,可以删除或更改StringFormat

    【讨论】:

    • 这非常接近我的需要,但我注意到一些事情 - 我的字体现在看起来很有趣,并且所有标签都需要调整大小以适应这种变化。另外,现在我将 30% 的时间花在 DrawString 函数上,这似乎并没有加快表单的响应速度。有什么想法吗?
    • 我不知道为什么会这样。字体到底是什么样子的?
    • 字母和字母间距看起来稍宽 - 在这两种情况下,它都是 MS Sans Serif 8.25 pt,但 FastLabel 更宽。
    【解决方案2】:

    好吧,分配 Text 属性大约需要 0.6 纳秒,不管是付出还是付出。昂贵的是副作用。您可能已经为标签打开了 AutoSize 属性。所以它需要创建字体句柄,在临时设备上下文中渲染文本,测量结果字符串,考虑到由于 TrueType 提示人为拉伸字母形状以使其与监视器上的像素重合的副作用,调整修改后的 ABC 指标以使 ClearType 工作。然后告诉本机 Windows 控件它需要更改其窗口大小。这将为标签以及作为标签控件父级的容器控件生成绘制事件。再次执行相同的程序,现在实际绘制像素。当启用 Aero 时,它会更改内存设备上下文中的字节,这些字节需要被传送到实际更新视频内存的视频设备驱动程序,以便用户可以看到结果。

    是的,这需要时间。

    通过编写您自己的代码而不是 Windows 窗体为您编写代码来加快速度。覆盖 OnPaint 事件,使用 TextRender.DrawText 绘制标签。在那里快速获胜,它很容易快 50 倍。减去设计器的点击便利性。

    【讨论】:

    • 我尝试快速使用这种方法,但我猜我需要做的不仅仅是创建一个简单的class MyFastLabel : Label 来覆盖 OnPaint 方法?仅使用该函数和 TextRenderer.DrawText() 方法,任何 MyFastLabel 都不会出现。还应该包括什么?
    • 我认为继承标签不会提供任何速度优势,除了双缓冲。
    • @slaks:你完全没有抓住重点。表单或面板可以绘制任何标签可以绘制的内容。
    • 我指的是他的评论。
    猜你喜欢
    • 1970-01-01
    • 2020-09-25
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 2017-08-19
    • 2019-10-02
    • 2021-12-30
    • 2010-10-03
    相关资源
    最近更新 更多