简体   繁体   English

蓝牙扫描在 Xamarin.iOS 中抛出 ArgumentOutOfRangeException

[英]Bluetooth Scan throwing ArgumentOutOfRangeException in Xamarin.iOS

I have a BLE scanning app that uses this plugin to continuously scan for nearby devices.我有一个 BLE 扫描应用程序,它使用这个插件来连续扫描附近的设备。 When devices are discovered, they are added to an ObservableRangeCollection (from James Montemagno's MvvmHelpers ).发现设备后,会将它们添加到 ObservableRangeCollection(来自 James Montemagno 的MvvmHelpers )。 If the device is already in the list and some of its data (eg, RSSI strength) changes, the collection is updated using ReplaceRange() .如果设备已经在列表中并且它的一些数据(例如,RSSI 强度)发生了变化,则使用ReplaceRange()更新集合。 If the device has been in the list for too long without updating, it is removed from collection.如果设备在列表中的时间过长而没有更新,则将其从集合中删除。

This is all working smoothly on Android, but it throws an ArgumentOutOfRange exception on iOS.这一切在 Android 上运行顺利,但它在 iOS 上引发 ArgumentOutOfRange 异常。 The exception doesn't always come at the same time, but if I leave the app running for long enough, it will eventually throw.异常并不总是同时出现,但如果我让应用程序运行足够长的时间,它最终会抛出。 Unfortunately, the stack trace doesn't point to anything in my code, so it's hard to tell whether this is something going on with the BLE Plugin, the ObservableRangeCollection plugin, or even Xamarin.Forms.不幸的是,堆栈跟踪没有指向我的代码中的任何内容,因此很难判断这是否与 BLE 插件、ObservableRangeCollection 插件甚至 Xamarin.Forms 相关。

Here is the exception message and stack trace:这是异常消息和堆栈跟踪:

{System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values.Parameter name: index
  at Xamarin.Forms.ListProxy.get_Item (System.Int32 index) [0x0000b] in D:\a\1\s\Xamarin.Forms.Core\ListProxy.cs:129 
  at Xamarin.Forms.ListProxy.System.Collections.IList.get_Item (System.Int32 index) [0x00000] in D:\a\1\s\Xamarin.Forms.Core\ListProxy.cs:443 
  at Xamarin.Forms.Internals.TemplatedItemsList`2[TView,TItem].get_Item (System.Int32 index) [0x00008] in <7d3a3d515f644268b15520ab8aaf1bfc>:0 
  at Xamarin.Forms.Platform.iOS.ListViewRenderer+ListViewDataSource.GetCellForPath (Foundation.NSIndexPath indexPath) [0x00007] in D:\a\1\s\Xamarin.Forms.Platform.iOS\Renderers\ListViewRenderer.cs:1327 
  at Xamarin.Forms.Platform.iOS.ListViewRenderer+ListViewDataSource.GetCell (UIKit.UITableView tableView, Foundation.NSIndexPath indexPath) [0x00021] in D:\a\1\s\Xamarin.Forms.Platform.iOS\Renderers\ListViewRenderer.cs:1036 
  at (wrapper managed-to-native) ObjCRuntime.Messaging.void_objc_msgSend(intptr,intptr)
  at UIKit.UITableView.EndUpdates () [0x0000d] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.16.0.13/src/Xamarin.iOS/UITableView.g.cs:294 
  at Xamarin.Forms.Platform.iOS.ListViewRenderer+<>c__DisplayClass52_0.<DeleteRows>b__0 () [0x00048] in D:\a\1\s\Xamarin.Forms.Platform.iOS\Renderers\ListViewRenderer.cs:599 
  at Xamarin.Forms.Platform.iOS.ListViewRenderer.DeleteRows (System.Int32 oldStartingIndex, System.Int32 oldItemsCount, System.Int32 section) [0x00046] in D:\a\1\s\Xamarin.Forms.Platform.iOS\Renderers\ListViewRenderer.cs:603 
  at Xamarin.Forms.Platform.iOS.ListViewRenderer.UpdateItems (System.Collections.Specialized.NotifyCollectionChangedEventArgs e, System.Int32 section, System.Boolean resetWhenGrouped) [0x00119] in D:\a\1\s\Xamarin.Forms.Platform.iOS\Renderers\ListViewRenderer.cs:542 
  at Xamarin.Forms.Platform.iOS.ListViewRenderer.OnCollectionChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x00000] in D:\a\1\s\Xamarin.Forms.Platform.iOS\Renderers\ListViewRenderer.cs:332 
  at Xamarin.Forms.Internals.TemplatedItemsList`2[TView,TItem].OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x0000a] in <7d3a3d515f644268b15520ab8aaf1bfc>:0 
  at Xamarin.Forms.Internals.TemplatedItemsList`2[TView,TItem].OnProxyCollectionChanged (System.Object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x0045f] in <7d3a3d515f644268b15520ab8aaf1bfc>:0 
  at Xamarin.Forms.ListProxy.OnCollectionChanged (System.Collections.Specialized.NotifyCollectionChangedEventArgs e) [0x0000a] in D:\a\1\s\Xamarin.Forms.Core\ListProxy.cs:232 
  at (wrapper other) System.Object.gsharedvt_out_sig(object&,intptr)
  at Xamarin.Forms.ListProxy+<>c__DisplayClass34_0.<OnCollectionChanged>b__0 () [0x00018] in D:\a\1\s\Xamarin.Forms.Core\ListProxy.cs:208 
  at (wrapper other) System.Object.__interp_lmf_mono_interp_entry_from_trampoline(intptr,intptr)
  at Foundation.NSAsyncActionDispatcher.Apply () [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.16.0.13/src/Xamarin.iOS/Foundation/NSAction.cs:152 
  at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain(int,string[],intptr,intptr)
  at UIKit.UIApplication.Main (System.String[] args, System.IntPtr principal, System.IntPtr delegate) [0x00005] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.16.0.13/src/Xamarin.iOS/UIKit/UIApplication.cs:86 
  at UIKit.UIApplication.Main (System.String[] args, System.String principalClassName, System.String delegateClassName) [0x0000e] in /Library/Frameworks/Xamarin.iOS.framework/Versions/13.16.0.13/src/Xamarin.iOS/UIKit/UIApplication.cs:65 
  at SDA.iOS.Application.Main (System.String[] args) [0x00001] in C:\Users\shodg\SDA\SDA\SDA.iOS\Main.cs:12 

Here is the relevant code in the viewmodel for adding/updating/removing devices from the ObservableRangeCollection:以下是视图模型中用于从 ObservableRangeCollection 添加/更新/删除设备的相关代码:

        public ObservableRangeCollection<DeviceListItemViewModel> Devices { get; set; } = new ObservableRangeCollection<DeviceListItemViewModel>();

        private void OnDeviceAdded(BleDevice device)
        {
            Devices.Add(new DeviceListItemViewModel(device));
        }

        private void OnDeviceUpdated(BleDevice device)
        {
            Devices.ReplaceRange(Devices.OrderByDescending(x => x.Rssi).ToList());
        }

        private void OnDeviceExpired(BleDevice device)
        {
            var vm = Devices.FirstOrDefault(d => d.Id == device.Id);
            Devices.Remove(vm);
        }

It appears that the exception has to do with ListView updates on iOS, and I've seen some threads on problems with ObservableCollections in Xamarin.iOS , but I'm having trouble determining if this issue lies in the Montemagno plugin or elsewhere, and what the best path forward is.似乎该异常与 iOS 上的 ListView 更新有关,我已经看到一些关于Xamarin.iOS 中的 ObservableCollections 问题的线程,但如果我在 Montemagno 插件有问题时确定了这个问题最好的前进道路是。

Any insight would be most welcome!任何见解都将受到欢迎!

So it turns out that the BLE scan, which runs continuously, was producing a race condition where an item was being removed at the same time that the list was being updated with removed devices.所以事实证明,持续运行的 BLE 扫描产生了一种竞争条件,其中一个项目被删除,同时列表被删除的设备更新。

Invoking on main thread and adding a lock to the property seems to keep that exception from throwing:在主线程上调用并向属性添加锁似乎可以防止抛出该异常:

        private object _deviceListLock = new object();
        public ObservableRangeCollection<DeviceListItemViewModel> Devices { get; set; } = new ObservableRangeCollection<DeviceListItemViewModel>();

        private void OnDeviceAdded(BleDevice device)
        {
            InvokeOnMainThread(() =>
            {
                lock (_deviceListLock)
                {
                    Devices.Add(new DeviceListItemViewModel(device));
                }
            });
        }

        private void OnDeviceUpdated(BleDevice device)
        {
            InvokeOnMainThread(() =>
            {
                lock (_deviceListLock)
                {
                    Devices.ReplaceRange(Devices.OrderByDescending(x => x.Rssi).ToList());
                }
            });
        }

        private void OnDeviceExpired(BleDevice device)
        {
            InvokeOnMainThread(() =>
            {
                lock (_deviceListLock)
                {
                    var vm = Devices.FirstOrDefault(d => d.Id == device.Id);
                    Devices.Remove(vm);
                }
            });
        }

Why this is necessary on iOS, but not on Android, I'm not entirely sure.为什么这在 iOS 上是必要的,而不是在 Android 上是必要的,我不完全确定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM