So aktualisieren Sie ein RichTextBox-Steuerelement aus der BackgroundWorker-Klasse mit BeginInvoke
Ich habe eine kleine app, die liest in einem Rohr delimted Datei und schreibt Zeilen in eine RTB, Hervorhebung, wenn es dissallowed Zeichen in bestimmte "Spalten". Das funktioniert perfekt...aber die Nutzer wollen einen Fortschrittsbalken und zu sehen, die Linien geschrieben wird, "live" und auch in der Lage sein, um abzubrechen, auf halbem Weg durch.
Habe ich folgende extension-Methode, die ich habe mit zu schreiben, auf eine RichTextBox ist, während die Blockierung der UI, aber dies fehlschlägt, mit einem BackgroundWorker mit BeginInvoke.
Fail ist, wenn Sie finden die aktuelle Länge des Textes.
public static void AppendLine(this RichTextBox richTextBox, string text, List<Char> foundChars, List<int> columns)
{
var split = text.Trim().Split(new char[] { '|' });
for (int i = 0; i < split.Count(); i++)
{
**var start = richTextBox.TextLength;**
richTextBox.AppendText(split[i]);
var end = richTextBox.TextLength;
if (columns.Contains(i + 1))
{
foreach (var foundChar in foundChars)
{
var current = start;
while (current > 0)
{
var position = richTextBox.Find(new char[] { foundChar }, current, end);
current = position + 1;
if (current > 0)
{
richTextBox.Select(position, 1);
richTextBox.SelectionColor = Color.Red;
}
}
}
}
richTextBox.SelectionLength = 0;
richTextBox.SelectionColor = Color.Black;
}
richTextBox.AppendLine();
}
private void UpdateResultsLine(string line, List<char> foundChars)
{
if (txtResults.InvokeRequired)
{
txtResults.BeginInvoke(new UpdateResultsLineDelegate(UpdateResultsLine), line, foundChars);
}
txtResults.AppendLine(line, foundChars, _fileType.ProcessColumns);
}
Jedoch, wenn ich rufe alle/all diese Erweiterungen in der gleichen Weise, die Sie arbeiten?
public static void AppendLine(this RichTextBox richTextBox)
{
richTextBox.AppendText(Environment.NewLine);
}
public static void AppendLine(this RichTextBox richTextBox, string text)
{
richTextBox.AppendText(text + Environment.NewLine);
}
public static void AppendLine(this RichTextBox richTextBox, string text, params object[] args)
{
richTextBox.AppendLine(string.Format(text, args));
}
Was bin ich? oder gibt es einen anderen Weg zu schreiben, farbigen text in eine RTB?
- Der Punkt mit der
BackgroundWorker
Komponente ist, dass Sie die Aktualisierung der Benutzeroberfläche in derProgressChanged
- und/oderRunWorkerCompleted
event-handler-Methoden. Sie brauchen nicht zu verwendenBeginInvoke
überhaupt. Siehe das Beispiel auf der MSDN-Website hier. - Sorry, aber nicht erfüllt voll meine Anforderungen. Ich brauche zu aktualisieren, mehr als eine RTB, plus wahrscheinlich ein label, und der Fortschrittsbalken. Ja, ich könnte ein neues Objekt erstellen, passieren rund, mit einem Enum zu sagen, was aktualisiert werden muss und wechseln in ProgressChanged-rufen, aber das scheint mir übertrieben.
- Ich verstehe nicht, warum Sie nicht aktualisieren mehrerer Steuerelemente innerhalb der
ProgressChanged
event-handler-Methode. Sie nicht brauchen, um keine Objekte erstellen oder übergeben Sie herum. Der Punkt, der Umgang mit diesen Ereignissen ist, dass Sie sind aufgezogen auf dem UI-thread. - Mein BackgroundWorker ist dabei die Arbeit, so dass nur ER weiß, was geändert wurde, wo es bis zu, welche Datei er gerade bearbeitet. Es kann sagen, das UI zu aktualisieren...aber was hat das UI eigentlich schreiben, um die RTB-wenn BW nicht passieren, dass die Informationen zurück?
- Auch beim aufrufen einer anderen richTextBox-Steuerelement.AppendText(...) funktioniert - und wenn in der Methode können Sie die TextLength-Eigenschaft...ich kann nicht sehen, warum das anders sein sollte?
BeginInvoke
wird es auf der dispatcher-Warteschlange für die Benutzeroberfläche. Je nachdem, wie viel Arbeit Sie tun im hintergrund ist es vielleicht nicht bekommen, um für eine Weile tatsächlich die Aktualisierung der Benutzeroberfläche. MitInvoke
wird eine Synchronisierung erzwingen damit Ihre hintergrund-Arbeiter haben zu warten, bis die UI wurde aktualisiert. Also mitInvoke
eher alsBeginInvoke
hat das Potenzial, zu verlangsamen Ihre eigentliche Arbeit, Handel es für eine regelmäßige Aktualisierung der Benutzeroberfläche.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Benötigen Sie eine
else
- Anweisung, die in derUpdateResultsLine
Methode. WennInvoke
erforderlich ist, werden Sie die Ausführung derUpdateResultsLine
- Methode über den Delegaten (aufrufen), aber dann rufen Sie wieder, ohne mitInvoke
Auch, warum verwenden Sie
BeginInvoke
(async), und verwenden SieInvoke
(sync)? Bist du sicher, dass du keine sync-Probleme? Mit Aufrufen und das hinzufügen einer else-Anweisung könnte, Ihre Probleme zu lösen:Hier, was Sie können versuchen, erstellen der extension-Klasse wie folgt
Und Wann immer und wo immer Sie wollen, Sie zu aktualisieren, alles auf Benutzeroberfläche, Sie müssen nur zu tun
Hoffe, das funktioniert für Sie.