Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using the C# Dispatcher in WPF Applications

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.

like image 513
Tombo890 Avatar asked Oct 20 '11 16:10

Tombo890


People also ask

What is the use of in C?

In C/C++, the # sign marks preprocessor directives. If you're not familiar with the preprocessor, it works as part of the compilation process, handling includes, macros, and more.

How do I start learning C?

Get started with C. Official C documentation - Might be hard to follow and understand for beginners. Visit official C Programming documentation. Write a lot of C programming code - The only way you can learn programming is by writing a lot of code.


2 Answers

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)); }); 
like image 106
Ricibob Avatar answered Sep 21 '22 23:09

Ricibob


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

This worked for me:

Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => {      // code... })); 
like image 38
MNicoll Avatar answered Sep 20 '22 23:09

MNicoll