C# RichEditBox имеет чрезвычайно низкую производительность (4 минуты загрузки)
RichEditBox
контроль в C# (я использую VS 2005) имеет плохую производительность. Я загружаю RTF-файл размером 2,5 МБ с 45 000 цветных строк текста в элемент управления, и это занимает 4 минуты. Я загружаю тот же RTF в элемент управления RTF в Wordpad Windows XP, и он загружается через 2 секунды.
Wordpad работает в 120 раз быстрее моего приложения.
В чем причина и как я могу это исправить?
1 ответ
Я загрузил исходный код Wordpad ( http://download.microsoft.com/download/4/0/9/40946FEC-EE5C-48C2-8750-B0F8DA1C99A8/MFC/ole/wordpad.zip.exe) и он имеет тот же худшее выступление (4 минуты). Но этот образец - старая версия Wordpad.
Таким образом, Microsoft за последние годы улучшила в Wordpad все, чего не хватает в.NET Framework.
Наконец я нашел решение:
.NET Framework использует класс RichEdit20W для элемента управления Richedit, как и старый Wordpad. Но WordPad Windows XP использует новый RichEdit50W, который был значительно улучшен Microsoft.
Итак, как мне сказать.NET Framework использовать 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);
}
}