0

I did a search and this is the closest thing to the question I have in mind How do I refresh visual control properties (TextBlock.text) set inside a loop?

The example included in that URL is exactly like in my situation, except that I am reading in a constant changing stream of data, and want the changes in values to be reflected in the Windows interface.

I am trying to make the program as efficient as possible, so should I use (INotifyPropertyChanged + Data Binding)

or following would be better?

Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Background, 
  new Action () => Label1.Content = some_content))

Assuming I perform a lot of buffer/checksum operations using system timers.

Community
  • 1
  • 1
Mittens
  • 35
  • 1
  • 11
  • AFAIK WPF data binding does not perform any thread synchronization automatically, so if your data arrives on a background thread you have no choice but to do a `BeginInvoke` (but it's perhaps disguised as `await` or `Dispatcher` calls). – stakx - no longer contributing Sep 21 '15 at 05:53
  • I am sorry I am a beginner programmer so I don't know what you meant by thread synchronization or a background thread. The RS232 data is read by using the SerialPort class, and the SerialPort method is called in either the DispatcherTimer or System.Timers event handlers. The read data is then assigned to the variables which I initialized in the main program/namespace – Mittens Sep 21 '15 at 06:02

1 Answers1

1

WPF, like most other UI frameworks, requires that you modify UI controls from the same thread on which they were created. This thread, often referred to as the "UI thread", is usually the application's main thread, i.e. the one where program execution started.

If you happen to subscribe to the SerialPort.DataReceived event, you are facing a problem, because that event might be triggered on any (background) thread:

The DataReceived event is raised on a secondary thread when data is received from the SerialPort object. Because this event is raised on a secondary thread, and not the main thread, attempting to modify some elements in the main thread, such as UI elements, could raise a threading exception. If it is necessary to modify elements in the main Form or Control, post change requests back using Invoke, which will do the work on the proper thread.

Meaning that inside your event handler, you may not directly manipulate any UI controls.

That is where WPF's Dispatcher.BeginInvoke comes in: It helps you to get some code back on the UI thread. You pass it a delegate, and that delegate will be invoked on the UI thread. Therefore you are allowed to manipulate the UI inside that delegate.

Data binding is no real alternative to BeginInvoke: Data binding also manipulates the UI, based on changes to some data object (or vice versa), but it does not automatically switch to the UI thread. This means that if you're using data binding, you must change the data context only if you're on the UI thread... so you need BeginInvoke anyway.

That all being said, if the use of data binding makes your code simpler and easier to understand, by all means use it! But you might still need Dispatcher.BeginInvoke:

private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
    Application.Current.Dispatcher.BeginInvoke(..., () => dataContext.SomeProperty = serialPort...;
}
stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
  • Thanks for your information! I asked this question because my supervisor asked me why I chose to use data binding instead of BeginInvoke. But your answer does give me some information on program threading. I don't use the DataReceived event because I heard it has problems, and since I know the frequency the data being sent, I will just pull all the Serial data to a circular buffer and read from there every 100ms. I'll try testing between DispatcherTimer and System.Timer and see if I need to use BeginInvoke. – Mittens Sep 21 '15 at 07:20