tags:

views:

74

answers:

2

I have an application that consists of a WPF UI with an "infrastructure" layer below it that has some references to various services with data. I've got a class, Updater, that has a couple properties that represent the data to be consumed by the UI layer. This updater has a Systems.Timer function such that every minute or so, it makes synchronous calls to the service and updates those aforementioned properties with a "refresh" of the data.

I'd like to raise an event from this class that the UI can be notified of the changes when it completes. When i did something akin to this previously, it was throwing exceptions right and left because the thread that fired the event was different (because it came from the timer elapsed event) then the thread the object was created on.

The crappy solution i'm using right now is to have another timer on the UI layer but...yuck.

What's the best way to notify the UI that the Updater class is all done with it's work?

+3  A: 

Those cross-thread exceptions can be solved by updating the UI through the Dispatcher.Invoke function. The Dispatcher is an object that can be used to call onto the UI thread. Give this article a thorough read and you should be all set.

Charlie
@Perplexed: Charlie's answer is a good one (+1). One warning: Ignore the last three paragraphs of the linked article since it contains inaccurate information: You should generally never use CheckAccess. Search my answers elsewhere on StackOverflow to learn the details. Otherwise that article is a great resource.
Ray Burns
I thought I tried that and it died a horrible death. Will try this out tomorrow and give credit where credit is due.
Perplexed
I think I got this to work - I don't know why it didn't work for me the first time, but I'm pretty sure I didn't use it correctly. I fire an event from the TimerElapsed function on the infrastructure layer, and it's handled by the UI layer. The function call on the UI is wrapped in the Dispatcher.Invoke().
Perplexed
A: 

The best way to do this is through binding if you're able. Implement the System.ComponentModel.INotifyPropertyChanged interface with your data classes and then bind your UI elements to the properties of these classes that you want to display. When the properties are updated, they fire a PropertyChanged event, which is handled internally by WPF dependency objects and updates your UI automatically. This is a way to avoid a lot of the plumbing that you would normally have to put together yourself to respond to updates.

This blog entry gives a nice example of how to use it, but there are many many more available online.

Jake
This will still throw an exception if you set the property from a non Ui thread.
Rusty
This would probably be a great way of doing it, but we're looking more for the quick and dirty.
Perplexed
Rusty's comment is correct; while this is a fine way to update bound properties, it will not prevent cross-thread exceptions.
Charlie
@Rusty, @Charlie Here is a sample of effecting a UI update from an asynchronous operation via binding. Am I missing something? http://www.mediafire.com/?0nmjzu3o2cz
Jake
@Rusty Can you explain a bit further? My example clearly shows a UI update being made through an asynchronous call without marshaling.
Jake
@Jake Please don't post download links...post your code on a blog or as a question.
Rusty