WPF大量添加文本块UI线程,但WinForms不会吗?

暗氢

我最近将我的应用程序从WinForms转换为WPF,并且对大多数新功能感到满意。但是,我遇到了一个主要的绊脚石。当我不断向文本框添加文本时,UI线程变得非常阻塞,以至于我只能看它添加文本而无法做任何事情!我需要能够在选项卡控件中切换选项卡,单击按钮等。奇怪的是,我在WinForms中的UI线程中绝对没有任何速度下降!

因此,这是我的应用程序的一些背景知识:它作为“动作队列”的一部分运行其他进程,并将这些进程的stdout和stderr吐出到两个单独的文本框以及日志文本框(这些是受影响的文本框)中。在输出较低的进程中,不会放慢速度,但是当我使用诸如SVN签出和文件复制之类的进程时,我会立即获得大量文本输出,因此只能执行追加文本。

这是我的打印代码:


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来加粗某些文本。如果有一种方法可以用不太麻烦的TextBox类提供粗体文本,请告诉我。

费德里科·贝拉萨特吉

WPFRichTextBox是一个非常重的UI元素,因为它不仅允许以WPF文档的形式提供丰富的内容,而且还具有编辑功能。

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

这是我的Log Viewer示例的小改编,它使用FlowDocumentScrollViewer代替了ItemsControl优点是,此UI元素允许选择和复制文本,同时保留您需要的RTF功能:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <FlowDocumentScrollViewer Document="{Binding}"/>
</Window>

背后的代码:

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<string> 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());
        }
    }

结果:

在此处输入图片说明

  • Once again, this proves that there's absolutely nothing you can achieve in winforms that can't be achieved with WPF, whereas the opposite can't be said, obviously. This makes winforms a practically obsolete technology that is literally replaced by newer, more capable ones.

  • Notice that I placed a 10 millisecond delay between each new entry. This is practically real time, and the UI does not show any slowing down or flickering or any quality degradation of any kind.

  • As with my other example, notice that most of the code behind is literally boilerplate to generate random text, the only relevant lines of code are paragraph.Inlines.Add(...).

  • WPF Rocks. - simply copy and paste my code in a File -> New Project -> WPF Application and see the results for yourself.

  • Let me know if you need further help.

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章