我们的Silverlight应用程序中存在一个问题,它使用WCF和实体框架,我们需要在用户通过关闭网页或浏览器而不是关闭silverlight应用程序来关闭应用程序时捕获事件。这是为了验证是否进行了任何更改,在这种情况下,我们会在离开之前询问用户是否要保存。
我们能够完成捕获网页关闭的部分:我们在应用程序对象中编写了一些代码,这些代码使网页调用silverlight应用程序对象中的方法。问题开始时,在此方法中,我们对Web服务进行异步调用以验证是否发生了更改(IsDirty)。我们使用DispatcherTimer来检查异步调用的返回。问题是异步调用永远不会完成(在调试模式下,它永远不会最终进入_BfrServ_Customer_IsDirtyCompleted方法),而在我们添加这个新功能之前它曾经工作正常。
您将在下面找到我们正在使用的代码。
我不熟悉将定时器与异步调用结合起来,所以我可能做错了但我无法弄清楚是什么。我也尝试了其他的东西,但我们没有任何成功..
======================代码======================== ======================
''# 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
答案 0 :(得分:0)
您的问题是DispatchTimer正在尝试在您使用Wait阻止的同一线程上执行代码。因此它无法提供滴答声。
我不确定我是否清楚为什么你需要计时器。为什么不直接在OnBeforeUnload
的调用中阻止UI线程(事实上你已经在做)。然后让异步回调函数在分配了值_IsDirty
。
点击等待消息框。