1

我正在使用带有 WPF 的 MVC 模型,并且在锁定 UI 时遇到了困难。该应用程序正在两个端点之间进行通信,并且 UI 有一个 TextBox,我将详细的通信日志写入该文本框。代码可以一次发送单个文件或多个文件。

我有一个特定的日志记录类,用于处理日志,因为它们需要创建、格式化和写入磁盘。我将 TextBox 传递给 Logging 类,然后使用 Dispatcher 对其进行写入,但是当我同时写入多个日志时,UI 会锁定。如果我只从一个发送的文件中写入日志,那么一切正常。

我试过添加一个线程锁,但这似乎没有解决任何问题。我什至锁定了整个写入过程(处理信息、写入磁盘和写入 UI),但仍然遇到相同的锁定问题。

下面列出了我用来写入 UI 的代码:

    /// <summary>
    /// Post the message to the UI.
    /// </summary>
    /// <param name="message">Message to post.</param>
    /// <param name="scrollToEnd">Scroll to the end of the Text Box if true</param>
    private void PostMessage(String message, bool scrollToEnd)
    {
        LoggingBox.Dispatcher.BeginInvoke(
            System.Windows.Threading.DispatcherPriority.Normal,
            new Action(delegate()
                {
                    LoggingBox.AppendText(message);
                    if (scrollToEnd)
                        LoggingBox.ScrollToEnd();
                }
            ));
    }

LogBox 只是一个文本框:

    /// <summary>
    /// Location for logs to be displayed.
    /// </summary>
    public TextBox LoggingBox { get; set; }

这是我第一次使用 WPF,所以我确信我犯了一个简单的错误。任何见解将不胜感激。

4

3 回答 3

1

我要更改的第一件事是将调度程序调用中的优先级设置为后台,这意味着日志更改请求仅在 UI 完成所有其他杂务时才得到处理。否则,您可以尝试在 StringBuilder 中收集日志条目,并且每秒钟左右更新一次 UI,以节省昂贵的屏幕更新。

于 2012-08-28T18:06:02.140 回答
0

Dispatcher只是主 UI 线程。它允许您在不同的DispatcherPriorities中安排进程以影响任务运行的时间,但是它仍然是一个线程,并且对其进行任何繁重的处理仍然会锁定您的 UI。

因此,所有繁重的处理都应该在另一个线程上完成,并且只有在 UI 线程上确实需要完成某些事情时才传递给调度程序线程。

我实际上建议更新string属性并将其绑定TextBox.Text到您的字符串,而不是TextBox直接更新。这将允许您在另一个线程中完成所有处理,而完全不用担心Dispatcher

此外,默认情况下 aTextBox具有设置为 true 的IsUndoEnabled属性。这使它保留了对文本的所有更改的历史记录,因此您可以使用撤消/重做热键。如果您不想切换到绑定,至少IsUndoEnabled=false在您的TextBox.

最后,就像hbarck 所说,将你的切换DispatcherPriority到更低的值,例如DispatcherPriority.Background.

于 2012-08-28T18:09:50.280 回答
0

在完成代码并禁用各个部分之后,我意识到发布到 UI 并不是导致 UI 冻结的原因。完成大部分工作的对象之一并没有被原始开发人员放在单独的线程上。创建线程后,UI 停止冻结。

感谢所有给予帮助的人。这里的社区很棒!

于 2012-09-11T16:20:50.220 回答