Silverlight 将Dispatchermer与异步调用结合使用

Silverlight 将Dispatchermer与异步调用结合使用,silverlight,dispatchertimer,Silverlight,Dispatchertimer,使用WCF和实体框架的Silverlight应用程序中存在一个问题,每当用户通过关闭网页或浏览器而不是关闭Silverlight应用程序关闭应用程序时,我们都需要捕获事件。这是为了验证是否进行了任何更改,在这种情况下,我们会询问用户是否希望在离开前保存 我们能够完成捕获网页关闭的部分:我们在应用程序对象中编写了一些代码,让网页在silverlight应用程序对象中调用一个方法。在该方法中,当我们对Web服务执行异步调用以验证是否发生了更改(IsDirty)时,问题就开始了。我们正在使用Dispa

使用WCF和实体框架的Silverlight应用程序中存在一个问题,每当用户通过关闭网页或浏览器而不是关闭Silverlight应用程序关闭应用程序时,我们都需要捕获事件。这是为了验证是否进行了任何更改,在这种情况下,我们会询问用户是否希望在离开前保存

我们能够完成捕获网页关闭的部分:我们在应用程序对象中编写了一些代码,让网页在silverlight应用程序对象中调用一个方法。在该方法中,当我们对Web服务执行异步调用以验证是否发生了更改(IsDirty)时,问题就开始了。我们正在使用Dispatcher来检查异步调用的返回。问题是异步调用永远不会完成(在调试模式下,它永远不会进入_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

您的问题是DispatchTimer试图在等待阻塞的同一线程上执行代码。因此它无法传递滴答声

我不太清楚你为什么需要计时器。为什么不直接在调用
OnBeforeUnload
时阻塞UI线程(事实上您已经这样做了)。然后让异步回调函数在分配了
\u IsDirty
的值后设置等待句柄


使用消息框跟随等待。

您的问题是DispatchTimer试图在等待阻塞的同一线程上执行代码。因此它无法传递滴答声

我不太清楚你为什么需要计时器。为什么不直接在调用
OnBeforeUnload
时阻塞UI线程(事实上您已经这样做了)。然后让异步回调函数在分配了
\u IsDirty
的值后设置等待句柄


使用消息框跟随等待。

欢迎使用SO,请花几分钟时间阅读常见问题解答和降价文档(编辑问题时,右侧空白处有一个有用的语法)。欢迎使用SO,请花几分钟时间阅读常见问题解答和降价文档(编辑问题时,可在右边空白处找到有用的语法)。