2013-07-25 20 views
9

sto ottenendo delle prestazioni quando la formattazione del testo in una RTB:lento formattazione del RichTextBox

<Grid> 
    <Grid.RowDefinitions> 
     <RowDefinition Height="Auto"/> 
     <RowDefinition/> 
    </Grid.RowDefinitions> 
    <StackPanel Orientation="Horizontal"> 
     <Button Click="ApplyFormatClick">ApplyFormat</Button> 
     <TextBlock x:Name="Time"/> 
    </StackPanel> 

    <RichTextBox x:Name="Rtb" Grid.Row="1"> 
     <RichTextBox.Document> 
      <FlowDocument> 
       <Paragraph> 
        <Run> 
         Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum 
        </Run> 
       </Paragraph> 
      </FlowDocument> 
     </RichTextBox.Document> 
    </RichTextBox> 
</Grid> 

codice dietro:

private readonly SolidColorBrush _blueBrush = Brushes.Blue; 
private void ApplyFormatClick(object sender, RoutedEventArgs e) 
{ 
    Stopwatch stopwatch = Stopwatch.StartNew(); 
    FlowDocument doc = Rtb.Document; 
    TextRange range = new TextRange(doc.ContentStart, doc.ContentEnd); 
    range.ClearAllProperties(); 
    int i = 0; 
    while (true) 
    { 
     TextPointer p1 = range.Start.GetPositionAtOffset(i); 
     i++; 
     TextPointer p2 = range.Start.GetPositionAtOffset(i); 
     if (p2 == null) 
      break; 
     TextRange tempRange = new TextRange(p1, p2); 
     tempRange.ApplyPropertyValue(TextElement.ForegroundProperty, _blueBrush); 
     tempRange.ApplyPropertyValue(TextElement.FontWeightProperty, FontWeights.Bold); 
     i++; 
    } 
    Time.Text = "Formatting took: " + stopwatch.ElapsedMilliseconds + " ms, number of characters: " + range.Text.Length; 
} 

Applicando la formattazione prende più di un secondo e quando si profiling i colpevoli sono:

I risultati del profiler sono piuttosto opachi per me.

Non ho mai usato FlowDocument e RichTextBox prima quindi probabilmente sto facendo questo molto sbagliato.

Il risultato finale è qualcosa di simile al VS find replace che evidenzierà le corrispondenze nel testo in base a un'espressione regolare modificabile.

Cosa si può fare in modo diverso per velocizzarlo? (Sample on Github)

risposta

8

suggerimento sarà di costruire manualmente il FlowDocument con la nuova formattazione (you can check the MSDN Magazine August 2007: WPF Flexible Content Display With Flow Documents, o il più recente articolo di MSDN Flow Document Overview), che permetterà di migliorare notevolmente le prestazioni, ad esempio, utilizzare il vostro esempio, se farlo manualmente come sotto, sulla mia macchina che otterrà il risultato in 52 ms, dove, come usando ApplyPropertyValue prenderanno 1266 ms:

private readonly SolidColorBrush _blueBrush = Brushes.Blue; 

private void ApplyFormatClick(object sender, RoutedEventArgs e) 
{ 
    Stopwatch stopwatch = Stopwatch.StartNew(); 
    FlowDocument doc = Rtb.Document; 
    TextRange range = new TextRange(doc.ContentStart, doc.ContentEnd); 
    Paragraph para = new Paragraph(); 
    string rangetem = range.Text; 
    range.ClearAllProperties(); 

    for(int i=0; i<rangetem.Count();i+=2) 
    { 
     Span s = new Span() { Foreground = _blueBrush }; 
     Bold b = new Bold(); 
     s.Inlines.Add(rangetem[i].ToString()); 
     b.Inlines.Add(s); 
     para.Inlines.Add(b); 
     if(i+1<rangetem.Count()) 
     { 
      para.Inlines.Add(rangetem[i + 1].ToString()); 
     } 
    } 
    doc.Blocks.Clear(); 
    doc.Blocks.Add(para); 

    Time.Text = "Formatting took: " + stopwatch.ElapsedMilliseconds + " ms, number of characters: " + range.Text.Length; 
} 
+0

Sì un drammatico impro vement davvero, fino a 38ms ora su un crap-top. –

+0

@Bolu Mi hai appena salvato la vita. Ho avuto un pezzo di codice con 'ApplyPropertyValue' che ha richiesto fino a 5 secondi per essere completato. Con la tua soluzione è super veloce. Grazie mille. Sai perché ci sono problemi di prestazioni con questa funzione? – Chostakovitch

+0

Link punta solo a una panoramica dei problemi MSDN ora. – Lennart

5

Se la funzionalità di nuovo non è necessario dal RichTextBox si può spremere un po 'più le prestazioni impostando IsUndoEnabled false

<RichTextBox IsUndoEnabled="False"> 
1

È possibile migliorare notevolmente le prestazioni del testo formattazione utilizzando i seguenti metodi:

rtb.BeginChange(); 

/// Your formating logic 

rtb.EndChange();