This project is read-only.

Chapter 10 - Lesson 3 code updated - Delegates

Sep 24, 2009 at 1:16 AM

So i was curious why Robert was having pbs with the form controls ( text and gridview ) not updating correctly.

I put a break point on where he was updating the text and looked into the textbox object..There was an exception thrown due to cross thread control update.

The watchers are in fact different threads, and calling a function to update controls on a different thread require the use of delegates and InvokeRequired..

I have fixed this part and added the form closing event to do some cleanup.





Sep 24, 2009 at 3:48 PM

Cross thread UI updates?!  Oh man, that's not a trivial thing to deal with!  Or at least I don't think so.  This would make for a great tutorial Souheil!  Can you post your thought patterns here to help noob like me on this?  Thanks.

Sep 24, 2009 at 11:27 PM


The code had this VB sub


Private Sub setProcessCount()

      Me.Label2.Text = String.Format("Number of processes: {0}", _dataTable.Rows.Count)

End Sub


This sub is called from 3 different places. The from load and the watchers.

The problem was that Label2 wasnt getting updated when the watchers' event handlers were called.

At first I suspected that there was something wrong with _dataTable.Rows.Count. So I put a break point there and looked at the number. Hmmm its correct.

So I hovered my mouse over the Me.Label2.Text and noticed that there was an exception thrown:

"Cross-thread operation not valid: Control 'Label2' accessed from a thread other than the thread it was created on." ...Interesting.

Next I Highlighted "ManagementEventWatcher" and pressed F1 and dug into the MSDN help for that class. At the bottom, in the Thread Safety section it says that Any instance members are not guaranteed to be thread safe..Bingo!

How To fix this issue.

There is a good artilce on MSDN "How to: Make Thread-Safe Calls to Windows Forms Controls"

Solution: Make use of InvokeRequired and delegates


Delegate Sub SetTextCallback(ByVal [text] As String)

Private Sub SetText(ByVal [text] As String)

If Me.Label2.InvokeRequired Then
   Dim del As New SetTextCallback(AddressOf SetText)
   Me.Invoke(del, New Object() {[text]})
   Me.Label2.Text = [text]
   'good place to refresh the datagridview and DoEvents since we are now thread safe
   End If
End Sub

Private Sub setProcessCount()

End Sub