Xamarin.iOS SIGSEGV 尝试发现连接的 BLE 外围设备的服务时
Xamarin.iOS SIGSEGV when trying to discover services of a connected BLE peripheral
我正在 Xamarin 中制作 BLE 跨平台应用程序,但无法发现连接的外围设备的服务。
这是共享项目中的精简代码,只是为了能够重现此问题;
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
}
问题是发现完成后,扫描停止,应用程序连接到外围设备,我们到达 ConnectedPeripheral (CBPeripheral peripheral) 函数,我得到一个SIGSEGV 崩溃并出现以下堆栈跟踪;
2015-04-21 23:33:37.205 BLE-test[1487:322866] critical: Stacktrace:
2015-04-21 23:33:37.206 BLE-test[1487:322866] critical: at <unknown> <0xffffffff>
2015-04-21 23:33:37.206 BLE-test[1487:322866] critical: at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr) <0xffffffff>
2015-04-21 23:33:37.207 BLE-test[1487:322866] critical: at UIKit.UIApplication.Main (string[],intptr,intptr) [0x00005] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:62
2015-04-21 23:33:37.207 BLE-test[1487:322866] critical: at UIKit.UIApplication.Main (string[],string,string) [0x0001c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:45
2015-04-21 23:33:37.208 BLE-test[1487:322866] critical: at BLEtest.Application.Main (string[]) [0x00008] in /Users/markus/Xamarin/BLE-test/BLE-test/Main.cs:17
2015-04-21 23:33:37.208 BLE-test[1487:322866] critical: at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) <0xffffffff>
后面是我符号化的本机堆栈跟踪;
Incident Identifier: DCFCEE70-3D12-4F69-8303-777B2959563D
CrashReporter Key: 25c23a5bf636eb183168b18867096174f0d59b79
Hardware Model: iPhone6,2
Process: BLE-test [1241]
Path: /private/var/mobile/Containers/Bundle/Application/C091012A-B1CB-464B-BDA5-B193C9C26BFC/BLE-test.app/BLE-test
Identifier: com.your-company.BLEtest
Version: 1.0 (1.0)
Code Type: ARM-64 (Native)
Parent Process: launchd [1]
Date/Time: 2015-04-21 22:22:57.387 +0200
Launch Time: 2015-04-21 22:22:56.120 +0200
OS Version: iOS 8.3 (12F70)
Report Version: 105
Exception Type: EXC_BAD_ACCESS (SIGABRT)
Exception Subtype: KERN_INVALID_ADDRESS at 0x000000000004b2c0
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x0000000195233270 __pthread_kill + 8
1 libsystem_pthread.dylib 0x00000001952d116c pthread_kill + 108
2 libsystem_c.dylib 0x00000001951aab14 abort + 108
3 BLE-test 0x00000001001f6878 mono_handle_native_sigsegv (mini-exceptions.c:2360)
4 BLE-test 0x0000000100200554 mono_sigsegv_signal_handler (mini.c:6879)
5 libsystem_platform.dylib 0x00000001952c8958 _sigtramp + 64
6 libobjc.A.dylib 0x0000000194aa5ea8 _class_getVariable + 160
7 libobjc.A.dylib 0x0000000194aa5ea8 _class_getVariable + 160
8 libobjc.A.dylib 0x0000000194a9a934 object_getInstanceVariable + 72
9 BLE-test 0x00000001002b10b0 get_raw_gchandle (runtime.m:304)
10 BLE-test 0x00000001002b1044 get_gchandle (runtime.m:311)
11 BLE-test 0x00000001002b0c6c xamarin_get_gchandle (runtime.m:317)
12 BLE-test 0x00000001002b0bc0 xamarin_get_nsobject_with_type_for_ptr_created (runtime.m:201)
13 BLE-test 0x00000001002b9508 xamarin_trampoline (.monotouch-trampoline-setup-callstack.inc:181)
14 CoreBluetooth 0x0000000182f37198 -[CBPeripheral handleServicesDiscovered:] + 740
15 CoreBluetooth 0x0000000182f34b38 -[CBPeripheral handleMsg:args:] + 280
16 CoreBluetooth 0x0000000182f309d0 -[CBCentralManager xpcConnection:didReceiveMsg:args:] + 160
17 libdispatch.dylib 0x00000001950ed990 _dispatch_call_block_and_release + 20
18 libdispatch.dylib 0x00000001950ed950 _dispatch_client_callout + 12
19 libdispatch.dylib 0x00000001950f80a0 _dispatch_queue_drain + 1444
20 libdispatch.dylib 0x00000001950f0a58 _dispatch_queue_invoke + 128
21 libdispatch.dylib 0x00000001950f1db8 _dispatch_main_queue_callback_4CF + 500
22 CoreFoundation 0x000000018327f7f4 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
23 CoreFoundation 0x000000018327d89c __CFRunLoopRun + 1488
24 CoreFoundation 0x00000001831a92d0 CFRunLoopRunSpecific + 392
25 GraphicsServices 0x000000018c9c76f8 GSEventRunModal + 164
26 UIKit 0x0000000187d6efa8 UIApplicationMain + 1484
27 BLE-test 0x00000001000a0b94 wrapper_managed_to_native_UIKit_UIApplication_UIApplicationMain_int_string___intptr_intptr + 340
28 BLE-test 0x000000010007e60c UIKit_UIApplication_Main_string___intptr_intptr + 44
29 BLE-test 0x000000010007e5c8 UIKit_UIApplication_Main_string___string_string + 184
30 BLE-test 0x0000000100050110 BLEtest_Application_Main_string__ + 160
31 BLE-test 0x000000010017c06c wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr + 156
32 BLE-test 0x0000000100202614 mono_jit_runtime_invoke (mini.c:6737)
33 BLE-test 0x000000010024d31c mono_runtime_invoke (object.c:2842)
34 BLE-test 0x00000001002513f8 mono_runtime_exec_main (object.c:4099)
35 BLE-test 0x00000001002afa34 xamarin_main (monotouch-main.m:400)
36 BLE-test 0x00000001001ca924 main + 92
37 libdyld.dylib 0x000000019511aa04 start + 0
观察与思考;
如果我在外围设备连接后删除委托,但在我尝试发现它的服务之前(这意味着我永远不会看到发现的结果,只是为了测试),DiscoverService例程不会导致崩溃;
// CurrentPeripheral.DiscoveredService += (object sender, NSErrorEventArgs e) => ...
// CurrentPeripheral.DiscoveredCharacteristic += (object sender, ...
同样,我也尝试将代表保留在上面,但删除了对 DiscoverServices 的实际调用,并且它也可以在不崩溃的情况下工作(这可能又是一个愚蠢的测试,但我只是想排除当我首先分配代表时发生的事情。
我也读过其他人对这类 issues/errors 的体验,有人说这是一个 GC 问题,即使对象仍然被引用,它也可能被 GC?
有人还提到在发布模式下工作但在调试模式下不行——所以我测试了 运行 我的应用程序在发布模式下似乎也能工作——但我没有任何 UI 所以我不能保证它确实有效——但我知道它确实 not 与 SIGSEGV 崩溃...
我很困惑。请帮助我理解 为什么 Xamarin 不喜欢我。我很乐意按照 Xamarin 规则进行调整和发挥,只要我了解约束条件以及我 can/can 不做的事情。
更新;
我只是想看看错误是不是里面的callback/event-handlers
CBPeripheral,或实际的 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-build 选项,其中可以更改 Linker Options。我认为 "Link all assemblies" 是一个不错的选择,只是为了安全起见,而不是预先选择的 "Don't link"。
没有多想,继续码字。
但是当我发现这个问题被提出并在这个线程中解释时,你拼命地开始到处搜索任何东西,我开始寻找 GC 问题,这被认为是错误的根源。因此,在 link (http://developer.xamarin.com/guides/cross-platform/deployment,_testing,_and_metrics/memory_perf_best_practices/) 阅读内存管理的最佳实践后,我发现;
The Link All Assemblies should be used with caution as it may break the application in unexpected ways.
因此,我改回 不要 link 现在一切都像一个魅力...
愚蠢的新手错误?是的,当然,但我希望犯同样错误的其他人会发现这个 post 并发现它有用。
谢谢,
/马库斯
我正在 Xamarin 中制作 BLE 跨平台应用程序,但无法发现连接的外围设备的服务。
这是共享项目中的精简代码,只是为了能够重现此问题;
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
}
问题是发现完成后,扫描停止,应用程序连接到外围设备,我们到达 ConnectedPeripheral (CBPeripheral peripheral) 函数,我得到一个SIGSEGV 崩溃并出现以下堆栈跟踪;
2015-04-21 23:33:37.205 BLE-test[1487:322866] critical: Stacktrace:
2015-04-21 23:33:37.206 BLE-test[1487:322866] critical: at <unknown> <0xffffffff>
2015-04-21 23:33:37.206 BLE-test[1487:322866] critical: at (wrapper managed-to-native) UIKit.UIApplication.UIApplicationMain (int,string[],intptr,intptr) <0xffffffff>
2015-04-21 23:33:37.207 BLE-test[1487:322866] critical: at UIKit.UIApplication.Main (string[],intptr,intptr) [0x00005] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:62
2015-04-21 23:33:37.207 BLE-test[1487:322866] critical: at UIKit.UIApplication.Main (string[],string,string) [0x0001c] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIApplication.cs:45
2015-04-21 23:33:37.208 BLE-test[1487:322866] critical: at BLEtest.Application.Main (string[]) [0x00008] in /Users/markus/Xamarin/BLE-test/BLE-test/Main.cs:17
2015-04-21 23:33:37.208 BLE-test[1487:322866] critical: at (wrapper runtime-invoke) object.runtime_invoke_dynamic (intptr,intptr,intptr,intptr) <0xffffffff>
后面是我符号化的本机堆栈跟踪;
Incident Identifier: DCFCEE70-3D12-4F69-8303-777B2959563D
CrashReporter Key: 25c23a5bf636eb183168b18867096174f0d59b79
Hardware Model: iPhone6,2
Process: BLE-test [1241]
Path: /private/var/mobile/Containers/Bundle/Application/C091012A-B1CB-464B-BDA5-B193C9C26BFC/BLE-test.app/BLE-test
Identifier: com.your-company.BLEtest
Version: 1.0 (1.0)
Code Type: ARM-64 (Native)
Parent Process: launchd [1]
Date/Time: 2015-04-21 22:22:57.387 +0200
Launch Time: 2015-04-21 22:22:56.120 +0200
OS Version: iOS 8.3 (12F70)
Report Version: 105
Exception Type: EXC_BAD_ACCESS (SIGABRT)
Exception Subtype: KERN_INVALID_ADDRESS at 0x000000000004b2c0
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x0000000195233270 __pthread_kill + 8
1 libsystem_pthread.dylib 0x00000001952d116c pthread_kill + 108
2 libsystem_c.dylib 0x00000001951aab14 abort + 108
3 BLE-test 0x00000001001f6878 mono_handle_native_sigsegv (mini-exceptions.c:2360)
4 BLE-test 0x0000000100200554 mono_sigsegv_signal_handler (mini.c:6879)
5 libsystem_platform.dylib 0x00000001952c8958 _sigtramp + 64
6 libobjc.A.dylib 0x0000000194aa5ea8 _class_getVariable + 160
7 libobjc.A.dylib 0x0000000194aa5ea8 _class_getVariable + 160
8 libobjc.A.dylib 0x0000000194a9a934 object_getInstanceVariable + 72
9 BLE-test 0x00000001002b10b0 get_raw_gchandle (runtime.m:304)
10 BLE-test 0x00000001002b1044 get_gchandle (runtime.m:311)
11 BLE-test 0x00000001002b0c6c xamarin_get_gchandle (runtime.m:317)
12 BLE-test 0x00000001002b0bc0 xamarin_get_nsobject_with_type_for_ptr_created (runtime.m:201)
13 BLE-test 0x00000001002b9508 xamarin_trampoline (.monotouch-trampoline-setup-callstack.inc:181)
14 CoreBluetooth 0x0000000182f37198 -[CBPeripheral handleServicesDiscovered:] + 740
15 CoreBluetooth 0x0000000182f34b38 -[CBPeripheral handleMsg:args:] + 280
16 CoreBluetooth 0x0000000182f309d0 -[CBCentralManager xpcConnection:didReceiveMsg:args:] + 160
17 libdispatch.dylib 0x00000001950ed990 _dispatch_call_block_and_release + 20
18 libdispatch.dylib 0x00000001950ed950 _dispatch_client_callout + 12
19 libdispatch.dylib 0x00000001950f80a0 _dispatch_queue_drain + 1444
20 libdispatch.dylib 0x00000001950f0a58 _dispatch_queue_invoke + 128
21 libdispatch.dylib 0x00000001950f1db8 _dispatch_main_queue_callback_4CF + 500
22 CoreFoundation 0x000000018327f7f4 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 8
23 CoreFoundation 0x000000018327d89c __CFRunLoopRun + 1488
24 CoreFoundation 0x00000001831a92d0 CFRunLoopRunSpecific + 392
25 GraphicsServices 0x000000018c9c76f8 GSEventRunModal + 164
26 UIKit 0x0000000187d6efa8 UIApplicationMain + 1484
27 BLE-test 0x00000001000a0b94 wrapper_managed_to_native_UIKit_UIApplication_UIApplicationMain_int_string___intptr_intptr + 340
28 BLE-test 0x000000010007e60c UIKit_UIApplication_Main_string___intptr_intptr + 44
29 BLE-test 0x000000010007e5c8 UIKit_UIApplication_Main_string___string_string + 184
30 BLE-test 0x0000000100050110 BLEtest_Application_Main_string__ + 160
31 BLE-test 0x000000010017c06c wrapper_runtime_invoke_object_runtime_invoke_dynamic_intptr_intptr_intptr_intptr + 156
32 BLE-test 0x0000000100202614 mono_jit_runtime_invoke (mini.c:6737)
33 BLE-test 0x000000010024d31c mono_runtime_invoke (object.c:2842)
34 BLE-test 0x00000001002513f8 mono_runtime_exec_main (object.c:4099)
35 BLE-test 0x00000001002afa34 xamarin_main (monotouch-main.m:400)
36 BLE-test 0x00000001001ca924 main + 92
37 libdyld.dylib 0x000000019511aa04 start + 0
观察与思考;
如果我在外围设备连接后删除委托,但在我尝试发现它的服务之前(这意味着我永远不会看到发现的结果,只是为了测试),DiscoverService例程不会导致崩溃;
// CurrentPeripheral.DiscoveredService += (object sender, NSErrorEventArgs e) => ...
// CurrentPeripheral.DiscoveredCharacteristic += (object sender, ...
同样,我也尝试将代表保留在上面,但删除了对 DiscoverServices 的实际调用,并且它也可以在不崩溃的情况下工作(这可能又是一个愚蠢的测试,但我只是想排除当我首先分配代表时发生的事情。
我也读过其他人对这类 issues/errors 的体验,有人说这是一个 GC 问题,即使对象仍然被引用,它也可能被 GC?
有人还提到在发布模式下工作但在调试模式下不行——所以我测试了 运行 我的应用程序在发布模式下似乎也能工作——但我没有任何 UI 所以我不能保证它确实有效——但我知道它确实 not 与 SIGSEGV 崩溃...
我很困惑。请帮助我理解 为什么 Xamarin 不喜欢我。我很乐意按照 Xamarin 规则进行调整和发挥,只要我了解约束条件以及我 can/can 不做的事情。
更新;
我只是想看看错误是不是里面的callback/event-handlers CBPeripheral,或实际的 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-build 选项,其中可以更改 Linker Options。我认为 "Link all assemblies" 是一个不错的选择,只是为了安全起见,而不是预先选择的 "Don't link"。
没有多想,继续码字。
但是当我发现这个问题被提出并在这个线程中解释时,你拼命地开始到处搜索任何东西,我开始寻找 GC 问题,这被认为是错误的根源。因此,在 link (http://developer.xamarin.com/guides/cross-platform/deployment,_testing,_and_metrics/memory_perf_best_practices/) 阅读内存管理的最佳实践后,我发现;
The Link All Assemblies should be used with caution as it may break the application in unexpected ways.
因此,我改回 不要 link 现在一切都像一个魅力... 愚蠢的新手错误?是的,当然,但我希望犯同样错误的其他人会发现这个 post 并发现它有用。
谢谢, /马库斯