2013-09-07 13 views
13

Sterowanie RichEditBox w języku C# (używam VS 2005) ma złą wydajność. Ładuję plik RTF 2,5 MB z 45 000 kolorowych linii tekstu do kontrolki i zajmuje to 4 minuty. Ładuję ten sam RTF do kontrolki RTF w Wordpad w Windows XP i ładuje się w 2 sekundy.C# RichEditBox ma bardzo niską wydajność (ładowanie 4 minuty)

Wordpad wykonuje 120 razy szybciej niż moja aplikacja.

Jaki jest powód i jak mogę to naprawić?

Odpowiedz

20

Pobrałem kod źródłowy WordPacka (http://download.microsoft.com/download/4/0/9/40946FEC-EE5C-48C2-8750-B0F8DA1C99A8/MFC/ole/wordpad.zip.exe) i ma on tę samą najgorszą wydajność (4 minuty). Ale ten przykład to stara wersja programu Wordpad.

Firma Microsoft udoskonaliła wszystko w Wordpad w ostatnich latach, których brakuje w środowisku .NET.

Wreszcie znalazłem rozwiązanie:

.NET Framework używa klasy RichEdit20W do kontroli RichEdit jak również stare Wordpad robi. Ale Wordpad systemu Windows XP korzysta z nowego RichEdit50W, który został bardzo ulepszony przez Microsoft.

Jak mogę powiedzieć, aby środowisko .NET używało RichEdit50W zamiast RichEdit20W?

To bardzo proste: wyprowadź klasę z RichTextBox i napisz zarządzaną opcją dla LoadLibary.

Klasa RichEdit50W jest tworzona przez MsftEdit.dll, która jest dostępna od wersji Windows XP SP1. Wdrożyłem awarię RichEdit20W w bardzo rzadkim przypadku, w którym ktoś nadal powinien używać XP bez dodatku Service Pack.

I to działa!

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

UWAGA: Patrz również 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); 
    } 
} 
+0

Wiesz co jeszcze poprawia się z RichEdit50W ponad 20W? Próbowałem użyć kodu do mojego własnego programu i nie widzę żadnej różnicy. –

+0

Czy załadowałeś duży tekst RTF z tysiącami linii, aby to przetestować? Czy używałeś SysInternals ProcessExplorer do sprawdzenia, która biblioteka DLL została załadowana do twojego procesu z modyfikacją kodu i bez niej? Przypuszczam, że zawsze ładuje tę samą bibliotekę DLL. Powinna istnieć ogromna różnica. Czy ustawiłeś punkt przerwania, aby sprawdzić, czy kod kiedykolwiek zostanie wykonany? – Elmue

+0

Tak, plik 4 MB z ponad 4000 linii. Obydwa ładunki trwają mniej niż 0,3 sekundy w obu wersjach 20W i 50W. Ogólne przewijanie i manipulacja są szybkie. Użyłem MessageBox.Show(), aby pokazać wersję 'i_Params.ClassName' zanim stała się" RichEdit50W "i zgodnie z oczekiwaniami była to" RichEdit20W ". –

Powiązane problemy