调用返回和页面的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条件被评估时,该值似乎为真
布尔值是处理此问题的好方法。您可以通过在回调请求后切换到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中。添加一个忙碌指示器,让用户知道正在进行操作。