31

I'm building a chat client and am not 100% sure on how to use the dispatcher. So the question is I have a method as such:

public void LostConnection()
{
    myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "\r\n");
}

Do i need to surrond the statement within (myGUI.chatBox... ) with a Dispatcher.Invoke? I appreciate any help.

4
  • That depends… On what thread does that method run? Also, just to be sure, you're using WPF, right? (Dispatcher works only with that.) Commented Oct 20, 2011 at 16:49
  • 1
    What UI framework are you using? (WinForms, WPF, or SL) There are differences between them Commented Oct 20, 2011 at 16:51
  • Yep, like svick suggests, it depends on if you're touching your UI from another thread (asynchronously) Commented Oct 20, 2011 at 16:52
  • 1
    My apologies were given below for not specifying that it is a wpf application and that it is my backend trying to update my GUI so yes it would be cross threading. I think I got it working though, so thanks to all of you who did help!!! Commented Oct 20, 2011 at 19:39

3 Answers 3

115

Your app has a main UI thread (usually ManagedThreadId==1). Typically in a chat app your events will come in on other threads (either dedicated socket listen threads or thread pool threads from listening code). If you want to update the UI from an event that gets pull on some other thread you must use the dispatcher. A useful test here is the Dispatcher.CheckAccess() method that returns true if code is on UI thread and false if on some other thread. A typical call looks something like:

using System.Windows.Threading; // For Dispatcher.

if (Application.Current.Dispatcher.CheckAccess()) {
    network_links.Add(new NetworkLinkVM(link, start_node, end_node));
}
else {
    Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(()=>{
        network_links.Add(new NetworkLinkVM(link, start_node, end_node));
    }));
}

If you're in the main window you can use:

Dispatcher.BeginInvoke(...

If you're in someother context eg a view model then use:

Application.Current.Dispatcher.BeginInvoke(  

Invoke vs BeginInvoke
Use Invoke if you want the current thread to wait until the UI thread has processed the dispatch code or BeginInvoke if you want current thread to continue without waiting for operation to complete on UI thread.

MessageBox, Dispatchers and Invoke/BeginInvoke:
Dispatcher.Invoke will block your thread until the MessageBox is dismissed.
Dispatcher.BeginInvoke will allow your thread code to continue to execute while the UI thread will block on the MessageBox call until its dismissed.

CurrentDispatcher vs Current.Dispatcher!
Be ware of Dispatcher.CurrentDispatcher as my understanding of this is that is will return a Dispatcher for the current thread not the UI thread. Generally are you interested in the dispatcher on the UI thread - Application.Current.Dispatcher always returns this.

Additional note:
If you are finding you are having to check dispatcher CheckAccess often then a useful helper method is:

public void DispatchIfNecessary(Action action) {
    if (!Dispatcher.CheckAccess())
        Dispatcher.Invoke(action);
    else
        action.Invoke();
}

Which can be called as:

DispatchIfNecessary(() => {
    network_links.Add(new NetworkLinkVM(link, start_node, end_node));
});
Sign up to request clarification or add additional context in comments.

4 Comments

Hey guys, sorry I didn't specify, yes it is a wpf application and yes it is cross threading. I am setting the delegate in the backend which then alerts my model which will then call that dispatcher method and update the gui interface. I still am not getting an option with intellesense to add a dispatcher but I will try to force it and see if it runs. Thanks guys! Any other tips?
If you have included using statement and use the Application.Current.Dispatcher you should get a result. If your "backend" is in a dll then you will need to pass the UI thread Dispatcher into your object there so it can reference it.
@Ricibob, just to be nitpicky, I think the UI thread doesn't always have to have Id of 1.
Plus one upvote because you write the using directive which helps a lot C# beginners.
4

I had problems with Application.Current.Dispatcher.BeginInvoke and the object.Invoke() methods.

This worked for me:

Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
{
     // code...
}));

1 Comment

This is what the accepted answer said some years ago. Duplicate answers shouldn't be posted.
2

Something like this (off the top of my head) should work:

public void LostConnection() 
{ 
   myGUI.Invoke
      ((MethodInvoker)delegate
   {
      myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "\r\n"); 
   });
}

2 Comments

That would be in WinForms. This question is apparently about WPF.
Yeah. That was not obvious from the question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.