调用返回和页面的OnNavigated事件之间的竞争条件

本文关键字:事件 之间 竞争 条件 OnNavigated 调用 返回 | 更新日期: 2023-09-27 18:15:08

我正在为windows phone 8构建一个使用IBM MobileFirst Platform Foundation 6.3的应用程序,我有一个像这样的流程。

在A页,用户轻按按钮,导航到B页。在B页,用户轻按其他按钮,发起呼叫。如果调用成功返回,则将用户带到c页。

Page A对应ViewModel Avm, Page A对应ViewModels Bvm和Cvm。因此,页B中的调用是由Bvm中的命令发起的,并且返回也在那里处理。

问题是这个流程。用户在B页发起调用,然后在调用返回之前,按Back键并导航到a页。然而,Bvm仍然存在,因此当调用返回时,用户从a页被带到C页。这是不允许的行为。

不幸的是,MobileFirst不支持取消请求,所以我不能在从页面导航时这样做。

我试过的:当调用返回时,在Bvm中设置一个bool变量来确定页面B是否是活动页面,并在页面的OnNavigatedTo和OnNavigatedFrom事件上更新它,这会创建一个竞争条件。如果调用在导航发生时返回,则不确定是否及时设置了变量。我对导航事件所做的任何改变都是一样的。

对于我该如何面对这个问题,你有什么建议吗?可能是在调用返回之前及时处理视图模型的一种方法。 编辑:更具体的数据和代码。在B页,Bvm有一个列表List<AddOnItemViewModel> AvailableAddonVMs,这个列表显示在屏幕上,调用该调用的命令在每个AddOnItemViewModel

页面B的OnNavigatedFrom代码

var vm = this.DataContext as AddOnsViewModel;
        if (e.NavigationMode == NavigationMode.Back)
        {
            foreach (var addOnVM in vm.AvailableAddonVMs)
            {                    
                addOnVM.IsStillOnPage = false;
                System.Diagnostics.Debug.WriteLine("go back" + addOnVM.AddOn.ServiceName + addOnVM.IsStillOnPage);
            }
        }
        base.OnNavigatingFrom(e);

AddOnItemViewModel代码

    #region check if still on page
            public bool IsStillOnPage = true;
            #endregion
    ...
    //Callback function
public void AfterEnableCheck(){
     Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        if (!IsStillOnPage)
                        {
                            System.Diagnostics.Debug.WriteLine("not on page now");
                            return;
                        }
                       // else continue with navigation
                       System.Diagnostics.Debug.WriteLine("continue navigation");
                    }
                   );
}

编辑2:示例流程和日志

Flow:调用在B页启动->返回之前按Back键,然后导航到A页->有时导航到C页,有时不会。

日志:

go back serviceName1 false

go back serviceName2 false

。.返回serviceNameX false

不在页面上(无法导航到C页)

继续导航(发生到C页的导航)。

奇怪的是,即使IsStillOnPage在每个AddOnItemViewModel上被设置为false,但有时当if条件被评估时,该值似乎为真

调用返回和页面的OnNavigated事件之间的竞争条件

布尔值是处理此问题的好方法。您可以通过在回调请求后切换到UI线程轻松地绕过竞争条件。我不知道IBM MobileFirst,但基本上应该是这样的:

private void RequestCallback()
{
    Dispatcher.BeginInvoke(() => 
    {
        // Here, we are in the UI thread
        if (isActive)
        {
            // The page is still active, trigger the navigation
            NavigationService.Navigate(...);
        }
    });
}

返回按钮按下,OnNavigatedTo, OnNavigatedFrom,和方法调用的调度程序都在UI线程中执行,所以你不必担心竞速条件

如果调用在页B中被调度,禁用Back按钮如何?通过这种方式,您可以确保应用程序在等待响应到达时保持在页面B中。添加一个忙碌指示器,让用户知道正在进行操作。