C# RichEditBox has extremely slow performance (4 minutes loading)
Asked Answered
G

1

16

The RichEditBox control in C# (I use VS 2005) has bad performance. I load an RTF file of 2,5 MB with 45.000 colored lines of text into the control and it takes 4 minutes. I load the same RTF into the RTF control in Wordpad of Windows XP and it loads in 2 seconds.

Wordpad performs 120 times faster than my application.

What is the reason, and how can I fix it?

Ghoul answered 7/9, 2013 at 1:59 Comment(0)
G
24

I downloaded the sourcecode of Wordpad (http://download.microsoft.com/download/4/0/9/40946FEC-EE5C-48C2-8750-B0F8DA1C99A8/MFC/ole/wordpad.zip.exe) and it has the same worst performance (4 minutes). But this sample is an old version of Wordpad.

So Microsoft has improved anything in Wordpad in the last years that is missing in the .NET framework.

Finally I found the solution:

The .NET framework uses the RichEdit20W class for the Richedit control as also the old Wordpad does. But the Wordpad of Windows XP uses the new RichEdit50W that has been highly improved by Microsoft.

So how do I tell the .NET framework to use RichEdit50W instead of RichEdit20W ?

This is very easy: Derive a class from RichTextBox and write a managed wrapper for LoadLibary.

The class RichEdit50W is created by MsftEdit.dll which is available since Windows XP SP1. I implemented a fallback to RichEdit20W for the very rare case that someone should still use XP without service pack.

And it works!

/// <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;
    }
}

NOTE: See also 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);
    }
}
Ghoul answered 7/9, 2013 at 1:59 Comment(4)
Do you know what else is improved with RichEdit50W over 20W? I tried using the code for my own program, and I can't notice any difference.Codpiece
Did you load a large RTF text with thousands of lines to test that? Did you use SysInternals ProcessExplorer to see which DLL is loaded into your process with and without the modification in code? I suppose it always loads the same DLL. There should be a huge difference. Did you set a breakpoint to see if the code ever executes?Ghoul
Yes, a 4MB file with over 4000 lines. Both loaded in less than 0.3 secs on both the 20W and 50W versions. General scrolling and manipulation appear as quick. I used MessageBox.Show() to show the version of the i_Params.ClassName before it became "RichEdit50W", and as expected it was "RichEdit20W".Codpiece
@Ghoul I used this to solve another problem here Thank you +1 :)Andresandresen

© 2022 - 2024 — McMap. All rights reserved.