【问题标题】:INotifyPropertyChanged Resubscribe not working, only the first time subscription workingINotifyPropertyChanged 重新订阅不起作用,只有第一次订阅起作用
【发布时间】:2022-01-04 11:32:06
【问题描述】:

我正在开发 Xamarin 应用程序,并与外部自定义设备通信。我的问题很奇怪,首先是应用程序启动,并自动连接到设备,所以一切都很好。当我突然从外部设备中取出电池时,蓝牙连接断开,并且工作正常,但是当我再次打开外部设备时,我的 Xamarin 应用程序连接得很好,但订阅不再工作了。

我调试了它,但不再调用了。我认为取消订阅/订阅过程是错误的。

...
if (ble.GetConnectionStatus())
            {
                Device.BeginInvokeOnMainThread(() =>
                {
                    ...
                    
                    ble.Adapter.DeviceConnectionLost -= Adapter_DeviceConnectionLost;
                    ble.Adapter.DeviceConnectionLost += Adapter_DeviceConnectionLost;
                    ble.PropertyChanged -= Ble_PropertyChanged;
                    ble.PropertyChanged += Ble_PropertyChanged;
                    data.PropertyChanged -= data_PropertyChanged;
                    data.PropertyChanged += data_PropertyChanged;
                    ...
                });
...

所以这太奇怪了,因为这是第一次工作,在启动应用程序时,但是当我在重新连接同一个订阅后调用它时不起作用。所以如果它错了,那为什么要在第一次工作呢?

我没有错误,只是重新订阅后不再触发函数。

如您所见,我需要“刷新”订阅。有没有其他方法可以解决这个问题?

【问题讨论】:

  • ble.PropertyChanged -= Ble_PropertyChanged; ble.PropertyChanged += Ble_PropertyChanged; 没有多大作用。如果你重新连接,你会得到一个新的实例吗?
  • @JeroenvanLangen 我在这个页面构造函数中创建了 ble 和数据实例,所以它不是一个新实例
  • 所以事件应该是完整的。
  • @JeroenvanLangen 你有什么建议我错了吗?
  • “如果它错了,那为什么要在第一次做这个?” 从你提供的信息很难说。作为测试,制作一个按钮,按下时从头开始:再次创建bledata。然后再次连接。这在这种情况下有效吗?如果是这样,则说明这些实例无法(并且可能无法)识别在创建实例之后连接的设备。

标签: c# xamarin.forms inotifypropertychanged


【解决方案1】:

如果那个“重新创建所有内容的按钮”有效,那么我看到了两种选择。


选项 1:

  • 有这样一个按钮,让用户可以手动“修复”这种情况。

专业版:为用户提供保证有效的解决方案。
缺点:需要用户干预。

选项 2:

  • 有一个周期性计时器,它决定是否/何时强制“修复”这种情况。

专业版:自动恢复。
缺点:如果在数据到达的同时强制恢复,则有丢失数据的风险。


在伪代码中,选项 2 可能是这样的:

// pseudo-code
static Timer timer = ..start a timer that has an event every 10 seconds.

OnTimerElapsed:
    if (!eventSeenRecently)
        ForceReset();
    eventSeenRecently = false;

..whereever you receive data..
    if (..has data..)
        eventSeenRecently = true;

这个概念是您跟踪是否继续接收数据。如果设备停止向您发送信息(但您认为应该如此),那么您“ForceReset” - 让一切重新开始所需的一切。



DeviceConnectionLost 还应该设置一些标志,当设备“恢复”时您可以使用它来强制重置。

// pseudo-code
DeviceConnectionLost:
    resetNeeded = true;

OnTimerElapsed:
    if (resetNeeded && ..test that device is available again..) {
        ForceReset();
        resetNeeded = false;
    }

也许这个自定义设备有一些可以提供帮助的选项或信息。

例如,可能有一种方法可以查询某些 id 或其他信息,因此您可以发现设备现在“不同”,需要重置。然后计时器执行该查询,并使用该信息来决定重置。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-05-14
    • 2017-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多