WPF附加文本阻止UI线程,但WinForms没有?

我最近将我的应用程序从WinForms转换为WPF,我对大多数新function感到满意。 然而,我遇到了一个重要的绊脚石。 当我不断地将文本附加到我的文本框时,UI线程变得如此封闭,以至于我无法做任何事情,只是看它附加文本! 我需要能够在我的选项卡控件,单击按钮等等中切换选项卡。奇怪的是,我在WinForms的UI线程中绝对没有减速!

所以,这里有一个关于我的应用程序的背景:它将其他进程作为“动作队列”的一部分运行,并将这些进程的stdout和stderr吐出到两个单独的文本框中,以及日志文本框(这些是受影响的文本框)。 在低输出进程中,没有减速,但是当我使用SVN checkout和文件复制等进程时,我会立即获得大量文本输出,它只能附加文本。

这是我的打印代码:

public void PrintOutput(String s) { String text = s + Environment.NewLine; Window.Dispatcher.Invoke(new StringArgDelegate(Window.PrintOutput), text); Debug.Log("d " + text); } public void PrintLog(String s) { ClearLogButtonEnabled = true; String text = s + Environment.NewLine; Window.Dispatcher.Invoke(new StringArgDelegate(Window.PrintLog), text); } 

和匹配的代码隐藏:

 public void PrintOutput(String s) { outputTextBox.AppendText(s); outputTextBox.ScrollToEnd(); if (!clearOutputButton.IsEnabled) clearOutputButton.IsEnabled = true; } public void PrintLog(String s) { logTextBox.AppendText(s); logTextBox.ScrollToEnd(); } 

这样我就没有得到一堆指责说我正在UI线程上做我的工作,这是我启动单独的工作线程的代码:

 Thread actionThread = new Thread(new ThreadStart(ActionManager.Instance().ExecuteActions)); actionThread.Name = "Action Manager Work Thread"; actionThread.Start(); 

这是处理所有辅助进程的启动,运行和清理的线程。 这些进程使用上面显示的打印方法来打印它们的stdout / stderr输出。 此外,每个进程都有自己的线程!

 Thread procThread = new Thread(new ThreadStart(StartProcess)); procThread.Name = action.Name + "_" + Guid.NewGuid(); procThread.Start(); 

我担心的是WPF在某种程度上对Invokes的速度较慢而且我搞砸了。 我花了很多工作将这个应用程序从WinForms切换到WPF,所以如果有人知道为什么我的打印速度会大幅下降,请告诉我!

编辑:

我还应该补充一点,我使用的是RichTextBox ,而不是TextBox ,我需要使用RichTextBox的function来加粗某些文本。 如果有办法提供粗体文本与不太繁琐的TextBox类请告诉我。

WPF RichTextBox是一个非常重量级的UI元素,因为它不仅允许WPF文档forms的丰富内容,而且还具有编辑function。

在这种情况下,您真正​​需要的是FlowDocumentScrollViewer 。

这是我的Log Viewer Sample的一个小改编,它使用FlowDocumentScrollViewer而不是ItemsControl 。 优点是此UI元素允许文本选择和复制,同时保留您需要的富文本function:

    

代码背后:

 public partial class MainWindow : Window { private System.Random random; private string TestData = "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"; private List words; private int maxword; private int index; private FlowDocument doc; private Paragraph paragraph; public MainWindow() { InitializeComponent(); DataContext = doc = new FlowDocument(); doc.Blocks.Add(paragraph = new Paragraph()); Task.Factory.StartNew(AddDataLoop); } private void AddDataLoop() { random = new Random(); words = TestData.Split(' ').ToList(); maxword = words.Count - 1; while (true) { Thread.Sleep(10); Dispatcher.BeginInvoke((Action) (AddRandomEntry)); } } private void AddRandomEntry() { var run = new Run(string.Join(" ", Enumerable.Range(5, random.Next(10, 50)) .Select(x => words[random.Next(0, maxword)]))); var isBold = random.Next(1, 10) > 5; if (isBold) paragraph.Inlines.Add(new Bold(run)); else paragraph.Inlines.Add(run); paragraph.Inlines.Add(new LineBreak()); } } 

结果:

在此处输入图像描述

  • 再一次,这certificate了在WPF中无法实现的winforms中绝对nothing可以实现,而显然是相反的。 这使得winforms成为一种几乎过时的技术,它实际上replaced更新,更强大的技术replaced

  • 请注意,我在每个新条目之间放置了10毫秒的延迟。 这实际上是实时的,并且UI不会显示任何类型的减速或闪烁或任何质量下降。

  • 与我的另一个例子一样,请注意,后面的大部分代码都是用于生成随机文本的样板文件,唯一相关的代码行是paragraph.Inlines.Add(...)

  • WPF Rocks。 – 只需将我的代码复制并粘贴到File -> New Project -> WPF Application然后自己查看结果。

  • 如果您需要进一步的帮助,请告诉我。