【问题标题】:C# RichEditBox has extremely slow performance (4 minutes loading)C# RichEditBox 性能极慢(加载 4 分钟)
【发布时间】:2023-03-25 11:05:02
【问题描述】:

C#(我使用 VS 2005)中的 RichEditBox 控件性能不佳。我将一个包含 45.000 彩色文本行的 2.5 MB 的 RTF 文件加载到控件中,这需要 4 分钟。我将相同的 RTF 加载到 Windows XP 的 Wordpad 中的 RTF 控件中,它会在 2 秒内加载。

Wordpad 的执行速度比我的应用程序快 120 倍。

这是什么原因,我该如何解决?

【问题讨论】:

    标签: c# winforms performance richtextbox


    【解决方案1】:

    我下载了写字板的源代码 (http://download.microsoft.com/download/4/0/9/40946FEC-EE5C-48C2-8750-B0F8DA1C99A8/MFC/ole/wordpad.zip.exe),它的性能同样最差(4 分钟)。但是这个示例是旧版本的写字板。

    因此,微软在过去几年中改进了写字板中 .NET 框架中缺少的任何内容。

    终于找到了解决办法:

    .NET 框架使用 RichEdit20W 类作为 Richedit 控件,就像旧的写字板一样。但是Windows XP的写字板使用的是经过微软高度改进的新RichEdit50W。

    那么我如何告诉 .NET 框架使用 RichEdit50W 而不是 RichEdit20W 呢?

    这很简单:从 RichTextBox 派生一个类并为 LoadLibary 编写一个托管包装器。

    RichEdit50W 类是由 MsftEdit.dll 创建的,该文件从 Windows XP SP1 开始可用。我实施了对 RichEdit20W 的回退,以解决在没有服务包的情况下仍应使用 XP 的极少数情况。

    而且它有效!

    /// <summary>
    /// The framework uses by default "Richedit20W" in RICHED20.DLL.
    /// This needs 4 minutes to load a 2,5MB RTF file with 45000 lines.
    /// Richedit50W needs only 2 seconds for the same RTF document !!!
    /// </summary>
    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams i_Params = base.CreateParams;
            try
            {
                // Available since XP SP1
                Win32.LoadLibrary("MsftEdit.dll"); // throws
    
                // Replace "RichEdit20W" with "RichEdit50W"
                i_Params.ClassName = "RichEdit50W";
            }
            catch
            {
                // Windows XP without any Service Pack.
            }
            return i_Params;
        }
    }
    

    注意:另请参阅http://msdn.microsoft.com/en-us/library/windows/desktop/bb787873%28v=vs.85%29.aspx

    public class Win32
    {
        [DllImport("kernel32.dll", EntryPoint="LoadLibraryW", CharSet=CharSet.Unicode, SetLastError=true)]
        private static extern IntPtr LoadLibraryW(string s_File);
    
        public static IntPtr LoadLibrary(string s_File)
        {
            IntPtr h_Module = LoadLibraryW(s_File);
            if (h_Module != IntPtr.Zero)
                return h_Module;
    
            int s32_Error = Marshal.GetLastWin32Error();
            throw new Win32Exception(s32_Error);
        }
    }
    

    【讨论】:

    • 您知道 RichEdit50W 比 20W 还改进了什么吗?我尝试将代码用于我自己的程序,但我没有发现任何区别。
    • 您是否加载了包含数千行的大型 RTF 文本来进行测试?您是否使用 SysInternals ProcessExplorer 来查看在修改和不修改代码的情况下将哪个 DLL 加载到您的进程中?我想它总是加载相同的DLL。应该有很大的不同。您是否设置了断点以查看代码是否执行过?
    • 是的,一个 4MB 的文件,超过 4000 行。在 20W 和 50W 版本上,两者都在不到 0.3 秒的时间内加载完毕。一般滚动和操作看起来很快。我使用 MessageBox.Show() 来显示 i_Params.ClassName 在它变为“RichEdit50W”之前的版本,正如预期的那样,它是“RichEdit20W”。
    • @Elmue 我用它来解决另一个问题here 谢谢+1 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-10
    • 1970-01-01
    • 2022-12-21
    • 1970-01-01
    • 1970-01-01
    • 2018-10-05
    相关资源
    最近更新 更多