Elmue Elmue - 9 months ago 37
C# Question

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


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?


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
        CreateParams i_Params = base.CreateParams;
            // Available since XP SP1
            Win32.LoadLibrary("MsftEdit.dll"); // throws

            // Replace "RichEdit20W" with "RichEdit50W"
            i_Params.ClassName = "RichEdit50W";
            // 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);