Calling methods with delegates and working with the UI from the called method in WPF
Wednesday, October 15, 2008 14:51The problem
I wanted to have a User Interface to call a long-running method and I wanted the long-running method to update the User Interface’s progress bar and status label.
The problem is that WPF does not support Application.DoEvents() method and runs the UI renderer in a particular UI-thread.
Working with threads
The first step to have an interactive UI is, of course, moving the working code into a separate thread.
To accomplish this, I created a class named SyncClass and put the code into the SyncMethod method.
From the calling UI I defined a delegate named SyncDelegate:
Delegate Sub SyncDelegate()
and an instance of the class:
Private WithEvents SyncInstance As SyncClass
Now, in order to invoke the SyncMethod asynchronously I used this piece of code:
Dim syncDeleg = New SyncDelegate(AddressOf SyncObject.SyncMethod) Dim ar = syncDeleg.BeginInvoke(Nothing, Nothing)

Now the problem: I wanted also to update the UI when an event of the working thread was raised.
Updating UI from a different thread
I firstly defined the events in the SyncClass (i.e. Successful, Failure, ActionChanged, …)
Public Event ActionChanged(ByVal NewAction As String)
then defined some handlers in the main thread (in this case in the main Window):
Private Sub SyncInstance_ActionChanged(ByVal NewAction As String) Handles SyncInstance.ActionChanged
The code inside the handler sub is ran in the working thread, not in the UI thread, so we have to use this code in order to pass informations to the UI:
Private Sub SyncInstance_ActionChanged(ByVal NewAction As String) Handles SyncInstance.ActionChanged
Me.Dispatcher.Invoke(New SyncInstance_ActionChanged_Aux_Delegate(AddressOf SyncInstance_ActionChanged_Aux), NewAction)
End Sub
Private Delegate Sub SyncInstance_ActionChanged_Aux_Delegate(ByVal NewAction As String)
Private Sub SyncInstance_ActionChanged_Aux(ByVal NewAction As String)
'Some code here. This piece will run in the UI thread
End Sub

Now you can put any code that uses UI environment in the auxiliary method.

