WPF文本框反应缓慢

3
我正在开发一个简单的串行数据查看器,用于监视发送到计算机串行端口的数据。我使用C#和WPF编写了一个测试应用程序;它只是将最近读取的行放入文本块中。然而,它会跳过每隔一行。我的理论是在WPF渲染窗口之前新数据被放入文本块。然而,我尝试了我能想到的所有线程优先级的组合,但最多只显示每隔一行;最糟糕的情况是每20行才显示一次。
我正在多核计算机上运行。我的应用程序由一个文本块和一个按钮来打开/关闭端口组成。(我已经尝试用文本框替换文本块,并且观察到相同的问题)
我的处理程序:
private void MainWindow_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    string message = sp.ReadLine();
    if (string.IsNullOrWhiteSpace(message))
        return;

    this.Dispatcher.BeginInvoke(DispatcherPriority.Send, (ThreadStart)delegate()
    {
        text.Text = message;
        this.InvalidateVisual();
    });
}

这个应用程序最重要的优先事项是处理大量数据的持续吞吐量;在这种情况下,WPF是否合适?如果合适,我做错了什么?

你尝试过创建一个公共字符串Message属性,实现INotifyChangedProperty,并直接将文本框绑定到该消息吗? - tbischel
3个回答

5
我知道我来晚了,但在与此问题抗争了一个月后,我终于发现了导致文本框更新缓慢的问题源头:
完全关闭文本包裹功能可以消除我的UI锁定问题:
TextWrapping="NoWrap"
当然,这意味着您需要更负责地确保在通过Environment.NewLine更新文本框之前正确地换行字符串,但在我看来这是一个很小的代价。
希望这能有所帮助。

这也解决了我们的问题。让我们的性能提升了大约100倍。 - omerts

3
我的公司的一个产品正在显示来自服务器的“准实时”数据更新,您可以尝试以下几个方法...
如果使用数据绑定而不是直接设置,您可能可以将text.Text移动到dispatcher调用之外。
您可以像这样进行操作:
添加一个依赖属性:
public static readonly DependencyProperty MessageTextProperty = 
    DependencyProperty.Register("MessageText", typeof(string), typeof(MyWidowClass), 
    new UIPropertyMetadata(string.Empty));

        public string MessageText
        {
            get { return (int)GetValue(MessageTextProperty ); }
            set { SetValue(MessageTextProperty , value); }
        }

在您的 XAML 文本框上:
<TextBox Text="{Binding Path=MessageText, ElementName=xNameOfMyWindow}"/>

其中xNameOfMyWindow是窗口标记的x:Name属性

现在您的代码应该像这样:

private void MainWindow_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    string message = sp.ReadLine();
    if (string.IsNullOrWhiteSpace(message))
        return;
    this.MessageText = message;
}

谢谢!还有一个问题 - 如果我想将所有传入的数据存储到文本框中,您会建议我使用什么作为数据存储容器?我听说过StringBuilder、List<string>和LinkedList<string>,但是我能将它们中的任何一个绑定到文本框吗? - CWMan
哦,还有一个提醒未来的读者:需要将“this.MessageText = message;”一行放入调用中,因为串口从单独的线程调用事件处理程序。 - CWMan
@CWMan,单独的线程是我之前不知道的信息!谢谢! - Muad'Dib
2
@CWMan,你最好的存储选择可能是一个ObservableCollection<string>(注意线程问题),然后使用ListBox并绑定到ItemSource,而不是TextBox。 - Muad'Dib
我很乐意,但应用程序的用户需要能够像普通文本框一样选择文本。我不认为列表框可以做到这一点? - CWMan
1
@CWMan,这是你需要做的。将列表框项的ItemTemplate设置为TextBox(类似于以下内容):<ListBox.ItemTemplate><DataTemplate><TextBox Text="{Binding}"/></DataTemplate></Listbox.ItemTemplate> - Muad'Dib

2
我有点晚了,但我遇到了这个问题。我发现 SpellCheck 属性似乎会减慢 WPF 文本框中的输入速度。由于我需要拼写检查,所以我通过添加一个简单的 Forms.Timer 来解决了这个问题:当用户开始输入时,文本框的 TextChanged 事件禁用拼写检查并启动计时器。然后,当一秒钟过去后,计时器的 Tick 事件会启用拼写检查。现在文本框的速度如它们应该的那样快了。希望这可以帮助遇到这个烦人问题的人。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接