Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
658 views
in Technique[技术] by (71.8m points)

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

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...