Using dispatchertimer in combination with an asynchroneous call

Posted by Civelle on Stack Overflow See other posts from Stack Overflow or by Civelle
Published on 2010-05-11T13:29:08Z Indexed on 2010/05/11 13:34 UTC
Read the original article Hit count: 563

Hi.

We have an issue in our Silverlight application which uses WCF and Entity Framework, where we need to trap the event whenever a user shuts down the application by closing the web page or the browser instead of closing the silverlight application. This is in order to verify if any changes have been made, in which case we would ask the user if he wants to save before leaving.

We were able to accomplish the part which consists in trapping the closing of the web page: we wrote some code in the application object that have the web page call a method in the silverlight application object. The problem starts when in this method, we do an asynchroneous call to the Web Service to verify if changes have occured (IsDirty). We are using a DispatcherTimer to check for the return of the asynchroneous call. The problem is that the asynchroneous call never completes (in debug mode, it never ends up stepping into the _BfrServ_Customer_IsDirtyCompleted method), while it used to work fine before we added this new functionality.

You will find belowthe code we are using.

I am new to writing timers in combination with asynchroneous call so I may be doing something wrong but I cannot figure out what. I tried other things also but we without any success..

====================== CODE ==============================================

'Code in the application object

Public Sub New()

InitializeComponent()

RegisterOnBeforeUnload()

_DispatcherTimer.Interval = New TimeSpan(0, 0, 0, 0, 500)

End Sub

Public Sub RegisterOnBeforeUnload()

'Register Silverlight object for availability in Javascript.

Const scriptableObjectName As String = "Bridge"

HtmlPage.RegisterScriptableObject(scriptableObjectName, Me)

'Start listening to Javascript event.

Dim pluginName As String = HtmlPage.Plugin.Id

HtmlPage.Window.Eval(String.Format("window.onbeforeunload = function () {{ var slApp = document.getElementById('{0}'); var result = slApp.Content.{1}.OnBeforeUnload(); if(result.length > 0)return result;}}", pluginName, scriptableObjectName))

End Sub

Public Function OnBeforeUnload() As String

Dim userControls As List(Of UserControl) = New List(Of UserControl)

Dim test As Boolean = True

If CType(Me.RootVisual, StartPage).LayoutRoot.Children.Item(0).GetType().Name = "MainPage" Then

If Not CType(CType(Me.RootVisual, StartPage).LayoutRoot.Children.Item(0), MainPage).FindName("Tab") Is Nothing Then

If CType(CType(Me.RootVisual, StartPage).LayoutRoot.Children.Item(0), MainPage).FindName("Tab").Items.Count >= 1 Then

For Each item As TabItem In CType(CType(Me.RootVisual, StartPage).LayoutRoot.Children.Item(0), MainPage).Tab.Items

If item.Content.GetType().Name = "CustomerDetailUI"

_Item = item

WaitHandle = New AutoResetEvent(False)

DoAsyncCall()

Exit

End If

Next

End If

End If

End If

If _IsDirty = True Then

Return "Do you want to save before leaving."

Else

Return String.Empty

End If

End Function

Private Sub DoAsyncCall()

_Item.Content.CheckForIsDirty(WaitHandle) 'This code resides in the CustomerDetailUI UserControl - see below for the code

End Sub

Private Sub _DispatcherTimer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles _DispatcherTimer.Tick

If Not _Item.Content._IsDirtyCompleted = True Then

Exit Sub

End If

_DispatcherTimerRunning = False

_DispatcherTimer.Stop()

ProcessAsyncCallResult()

End Sub

Private Sub ProcessAsyncCallResult()

_IsDirty = _Item.Content._IsDirty

End Sub

'CustomerDetailUI code

Public Sub CheckForIsDirty(ByVal myAutoResetEvent As AutoResetEvent)

_AutoResetEvent = myAutoResetEvent

_BfrServ.Customer_IsDirtyAsync(_Customer) 'This method initiates asynchroneous call to the web service - all the details are not shown here

_AutoResetEvent.WaitOne()

End Sub

Private Sub _BfrServ_Customer_IsDirtyCompleted(ByVal sender As Object, ByVal e As BFRService.Customer_IsDirtyCompletedEventArgs) Handles _BfrServ.Customer_IsDirtyCompleted

If _IsDirtyFromRefesh Then

_IsDirtyFromRefesh = False

If e.Result = True Then

Me.Confirm("This customer has been modified. Are you sure you want to refresh your data ? " & vbNewLine & " Your changes will be lost.", "Yes", "No", Message.CheckIsDirtyRefresh)

End If

Busy.IsBusy = False

Else

If e.Result = True Then

_IsDirty = True

Me.Confirm("This customer has been modified. Would you like to save?", "Yes", "No", Message.CheckIsDirty)

Else

Me.Tab.Items.Remove(Me.Tab.SelectedItem)

Busy.IsBusy = False

End If

End If

_IsDirtyCompleted = True

_AutoResetEvent.Set()

End Sub

© Stack Overflow or respective owner

Related posts about dispatchertimer

Related posts about Silverlight