Tim
Tim

Reputation: 2911

Dispatcher Locking UI

I am using the MVC model with WPF, and am having difficulties with the UI locking up. The application is communicating between two endpoints, and the UI has a TextBox that I write detailed logs of the communication to. The code may either send a single file or multiple files in a burst.

I have a specific logging class that I use to process the logs, since they need to be created, formatted, and written to disk. I pass the TextBox to the Logging class, and then use a Dispatcher to write to it, but when I have several logs writing at the same time, the UI locks up. If I am only writing logs from a single sent file, everything works fine.

I have tried adding a Thread Lock, but this doesn't seem to fix anything. I've even locked the entire writing process (processing the information, writing to disk, and writing to the UI), but continue to get the same locking problems.

The code I use to write to the UI is listed below:

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

The LogBox is just a TextBox:

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

This is my first time working with WPF,so I am sure there is a simple mistake that I am making. Any insight would be greatly appreciated.

Upvotes: 1

Views: 1661

Answers (3)

Tim
Tim

Reputation: 2911

After following through the code, and disabling various parts, I realized that posting to the UI was not what was causing the UI to freeze. One of the objects that did a majority of the work had not been put on a separate thread by the original developer. After creating the thread, the UI stopped freezing.

Thank you to everyone who gave assistance. The community here is awesome!

Upvotes: 0

Rachel
Rachel

Reputation: 132568

The Dispatcher is simply the main UI thread. It allows you to schedule processes at different DispatcherPriorities to affect when the task runs, however it is still a single thread and doing any heavy processing on it will still lock up your UI.

Because of this, all heavy processing should be done on another thread and only passed to the dispatcher thread when something actually needs to be done on the UI thread.

I would actually suggest updating a string property and binding the TextBox.Text to your string instead of updating the TextBox directly. This would allow you to do all your processing in another thread and not worry about the Dispatcher at all.

In addition, by default a TextBox has an IsUndoEnabled property that is set to true. This makes it maintain a history of all changes to the text so you can use undo/redo hotkeys. If you don't want to switch to a binding, at least set IsUndoEnabled=false on your TextBox.

And finally, like hbarck said, switch your DispatcherPriority to something lower such as DispatcherPriority.Background.

Upvotes: 0

hbarck
hbarck

Reputation: 2944

The first thing I'd change is to set the priority in the dispatcher call to Background, which means the log change requests only get processed when the UI is done with all its other chores. Otherwise, you could try to collect log entries in a StringBuilder and only update the UI every second or so, in order to save expensive screen updates.

Upvotes: 1

Related Questions