Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/xamarin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
尝试发现已连接外围设备的服务时,Xamarin.iOS SIGSEGV_Xamarin_Xamarin.ios_Core Bluetooth_Xamarin Studio - Fatal编程技术网

尝试发现已连接外围设备的服务时,Xamarin.iOS SIGSEGV

尝试发现已连接外围设备的服务时,Xamarin.iOS SIGSEGV,xamarin,xamarin.ios,core-bluetooth,xamarin-studio,Xamarin,Xamarin.ios,Core Bluetooth,Xamarin Studio,我正在Xamarin中制作一个可扩展的跨平台应用程序,但无法发现连接的外围设备的服务 这是共享项目中的精简代码,只是为了能够重现这个问题 internal class BleTransport { //Private stuff private CBCentralManager Central = null; private CBPeripheral CurrentPeripheral = null; private bool IsScanning = false

我正在Xamarin中制作一个可扩展的跨平台应用程序,但无法发现连接的外围设备的服务

这是共享项目中的精简代码,只是为了能够重现这个问题

internal class BleTransport
{
    //Private stuff
    private CBCentralManager Central = null;
    private CBPeripheral CurrentPeripheral = null;
    private bool IsScanning = false;

    internal BleTransport ()
    {
        //Constructor -- initialize everything that needs to be initialized!
        Central = new CBCentralManager (DispatchQueue.MainQueue);

        //Setup delegates to the central's events
        Central.UpdatedState += (object sender, EventArgs e) => CentralStateChanged.Set ();
        Central.DiscoveredPeripheral += (object sender, CBDiscoveredPeripheralEventArgs e) => DiscoveredPeripheral (e.Peripheral, e.RSSI, e.AdvertisementData);             
        Central.ConnectedPeripheral += (object sender, CBPeripheralEventArgs e) => ConnectedPeripheral (e.Peripheral);
        Central.FailedToConnectPeripheral += (object sender, CBPeripheralErrorEventArgs e) => FailedToConnectPeripheral (e.Error, e.Peripheral);
        Central.DisconnectedPeripheral += (object sender, CBPeripheralErrorEventArgs e) => DisconnectedPeripheral (e.Error, e.Peripheral);
    }

    readonly AutoResetEvent CentralStateChanged = new AutoResetEvent (false);
    private async Task<bool> WaitForCentralState (CBCentralManagerState state, TimeSpan timespan)
    {
        Console.WriteLine("Waiting for state : " + state);

        //TODO; Keep track of time and decrease time-span accordingly
        bool timedout = false;

        while (!timedout && Central.State != state) 
        {
            timedout = await Task.Run (delegate {
                //WaitOne returns false if we timeout
                return !CentralStateChanged.WaitOne (timespan);
            });
        }

        //Return true if we made it, amd false if we timedout
        return !timedout;
    }

    private void StartScanning()
    {
        Console.WriteLine("Start scan requestd!");

        if (!IsScanning) 
        {
            //Start!
            IsScanning = true;

            Console.WriteLine("Kicking scan for peripherals!");
            CBUUID[] uuids = null;
            Central.ScanForPeripherals (uuids);
        }
    }

    private void StopScanning()
    {
        Console.WriteLine("Stop scan requested!");

        if (IsScanning) 
        {
            //Stop!
            IsScanning = false;
            Central.StopScan();
        }
    }

    public async Task<bool> SetupTransport ()
    {
        Console.WriteLine("Setting up transport!");

        //Wait for state update...
        if (!await WaitForCentralState (CBCentralManagerState.PoweredOn, TimeSpan.FromSeconds (2))) {

            //Failed detecting a powered-on BLE interface
            Console.WriteLine("Failed detecting usable BLE interface!");
            return false;
        }

        //Kick scanning... 
        StartScanning();

        //Wait for discovery and connection to a valid peripheral, or timeout trying...
        await Task.Delay(10000);

        return true;
    }

    #region Internal BLE utility methods

    private void DiscoveredPeripheral (CBPeripheral peripheral, NSNumber rssi, NSDictionary advertisementData)
    {
        Console.WriteLine("DiscoveredPeripheral: " +peripheral.Name);

        //If the discovered device's name IS a valid serial number, AND match the serial number that we're intended to establish connection to...
        if (peripheral.Name == "MyPeripheralName") {

            Console.WriteLine("It's the peripheral we're looking for!");

            //Stop scanning...
            StopScanning();

            //Save reference and connect to it!
            CurrentPeripheral = peripheral;
            Central.ConnectPeripheral(CurrentPeripheral, new PeripheralConnectionOptions());
        }
    }

    private void ConnectedPeripheral (CBPeripheral peripheral)
    {
        Console.WriteLine("ConnectedPeripheral: " + peripheral.Name);

        //Great -- explore services and charateristics and don't stop until we know that this device is legit!
        CurrentPeripheral.DiscoveredService +=  (object sender, NSErrorEventArgs e) => DiscoveredServices (e.Error);        
        CurrentPeripheral.DiscoveredCharacteristic += (object sender, CBServiceEventArgs e) => DiscoveredCharacteristics (e.Error, e.Service);

        //Kick service discovery!
        CurrentPeripheral.DiscoverServices();
    }

    private void FailedToConnectPeripheral (NSError error, CBPeripheral peripheral)
    {
        Console.WriteLine("FailedToConnectPeripheral: " + peripheral.Name);
    }

    private void DisconnectedPeripheral (NSError error, CBPeripheral peripheral)
    {
        Console.WriteLine("DisconnectedPeripheral: " + peripheral.Name + "(Error = " + error + ")");
    }

    private void DiscoveredServices (NSError error)
    {
        Console.WriteLine("DiscoveredService: " + error + "  -- " + NSThread.Current.IsMainThread);
        if (error != null) {

            //No error -- great!
            foreach (CBService service in CurrentPeripheral.Services) {
                Console.WriteLine ("Discovered service: " + service);
            }
        } 
        else 
        {
            //Opps -- failed!

            //Disconnect and indicate connection attempt finished
        }
    }

    private void DiscoveredCharacteristics (NSError error, CBService service)
    {
        Console.WriteLine("DiscoveredCharacteristics for service: " + service);
        if (error != null) {

            //No error -- great!
            foreach (CBCharacteristic characteristic in service.Characteristics) {
                Console.WriteLine ("Discovered charateristic: " + characteristic);
            }
        } 
        else 
        {
            //Opps -- failed!

            //Disconnect and indicate connection attempt finished
        }
    }

    #endregion
}
观察和思考; 如果在连接外围设备之后,但在我尝试发现其服务之前(这意味着我将永远看不到发现的结果,只是为了测试),将代理移除到外围设备,DiscoverService例程不会导致崩溃

// CurrentPeripheral.DiscoveredService += (object sender, NSErrorEventArgs e) => ...    
// CurrentPeripheral.DiscoveredCharacteristic += (object sender, ... 
类似地,我也尝试保留上面的代理,但删除了对DiscoverServices的实际调用,这也可以在不崩溃的情况下工作(这可能也是一个愚蠢的测试,但我只是想排除在一开始分配代理时发生的事情)

我也读过其他人遇到此类问题/错误的经历,有人说这是一个GC问题,其中一个对象可能是GC的,即使它仍然被引用

有人还提到,东西在发布模式下工作,但在调试模式下不工作——所以我测试了在发布模式下运行我的应用程序,它似乎也工作——但我没有任何UI,所以我不能保证它确实工作——但我确实知道它不会与SIGSEGV一起崩溃

我很困惑。请帮助我理解为什么Xamarin不喜欢我。我很乐意按照Xamarin的规则进行调整和比赛,只要我理解这些限制以及我能/不能做什么

更新日期; 我只是想看看错误是不是源代码中的回调/事件处理程序 cbperipal,或实际的DiscoverServices方法调用。所以我试着打电话 启动该功能并等待500毫秒,然后查看是否已在中发现服务 我的外围对象

Console.WriteLine ("List of services (before discovery attempt)");
if (CurrentPeripheral.Services != null)
    foreach (CBService service in CurrentPeripheral.Services) {
        Console.WriteLine ("Service: " + service);
}

CurrentPeripheral.DiscoverServices();
await Task.Delay(500);

Console.WriteLine ("List of services (after discovery attempt)");
if (CurrentPeripheral.Services != null)
    foreach (CBService service in CurrentPeripheral.Services) {
        Console.WriteLine ("Service: " + service);
}
。。。而且它有效!因此,这意味着对DiscoverServices的调用是有效的
很好,但是回调不起作用

好的,问题解决了。当然是新手的事

当我启动Xamarin Studio并开始这个项目时,我到处玩,查看不同的选项、设置、功能、菜单等,只是为了掌握这个概念。我发现的其中一件事是iOS构建选项,人们可以在其中更改链接器选项。为了安全起见,我认为“链接所有程序集”是一个不错的选择,而不是预先选择的“不链接”

没有多想,继续编码

但是当我发现在这个帖子中提出并解释的问题时,你拼命地开始在任何地方搜索任何东西,我开始寻找GC问题,我认为这是错误的根源。因此,通过阅读此链接()中的内存管理最佳实践,我发现:

The Link All Assemblies should be used with caution as it may break the application in unexpected ways.
因此,我改回不链接,现在一切都像一个魅力工程。。。 愚蠢的新手错误?是的,当然,但我希望其他犯同样错误的人会发现这篇文章并觉得它有用

谢谢,
/马库斯

你能给我你的蓝牙样品吗?我到处都找不到合适的样品。谢谢
Console.WriteLine ("List of services (before discovery attempt)");
if (CurrentPeripheral.Services != null)
    foreach (CBService service in CurrentPeripheral.Services) {
        Console.WriteLine ("Service: " + service);
}

CurrentPeripheral.DiscoverServices();
await Task.Delay(500);

Console.WriteLine ("List of services (after discovery attempt)");
if (CurrentPeripheral.Services != null)
    foreach (CBService service in CurrentPeripheral.Services) {
        Console.WriteLine ("Service: " + service);
}
The Link All Assemblies should be used with caution as it may break the application in unexpected ways.