1

I'm trying to create a custom, in-house application that is going to access other internal systems which broadcast their names and IP addresses via UDP. I'm trying to create a multi-threaded dialog that polls for UDP messages every 500 ms for 15 seconds, parses the UDP messages and then adds the names of the detected systems to a ListBox in the dialog, updating it in real time. I've already got the UDP scanning code tested and done, the only problem is updating the ListBox across threads. Any time I try to access the ListBox's Items or ItemSource properties, I get a System.InvalidOperationException : "The calling thread cannot access this object because a different thread owns it."

The relevant stack trace portion:

 at System.Windows.Threading.Dispatcher.VerifyAccess() at System.Windows.DependencyObject.SetValue(DependencyProperty dp, Object value) at System.Windows.Controls.ItemsControl.set_ItemsSource(IEnumerable value) 

This occurs regardless of whether I'm using an ObservableCollection (I know, has nothing to do with the collection type), a HashSet or any other object. Can anybody help me with accessing the GUI across different threads ?

2 Answers 2

5

You can't access the gui safely from other threads. All calls have to be dispatched via a call to Invoke to be executed on the main thread. This is a legacy hang-up that Windows has been saddled with for years.

Here's a snippet of code that should get you started... (found here: http://social.msdn.microsoft.com/forums/en-US/wpf/thread/360540eb-d756-4434-86f9-a3449f05eb55/ )

if(textbox.Dispatcher.CheckAccess()) { // The calling thread owns the dispatcher, and hence the UI element textbox.AppendText(...); } else { // Invokation required textbox.Dispatcher.Invoke(DispatcherPriority.Normal, [delegate goes here]); } 

There is additional clarification here: http://channel9.msdn.com/forums/TechOff/251835-WPF-Invoke-and-Anonymous-delegates/

Sign up to request clarification or add additional context in comments.

2 Comments

Wow, that was an amazingly useful answer, and it did the trick. Thank you so much. I'd up-vote your answer a dozen more times if I could.
Also note you can dispatch back to the UI thread asynchronously as well using the Dispatcher.BeginInvoke / EndInvoke pattern
2

As Andrew already said, you should synchronize the access to GUI across the threads (it's just the way it is - you can't do much about it).

However, Dispatcher is a WPF-specific synchronization mechanism. If you'd like to stick to a more general approach, then take a look at System.Threading.SynchronizationContext class.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.