简体   繁体   English

Xamarin.Mac事件和线程似乎无法一起使用

[英]Xamarin.Mac events and threads don't seem to work together

I'm having loads of difficulty with Xamarin.Mac at the moment. 目前,我在使用Xamarin.Mac时遇到很多困难。

Basically all I want to do is to POST and Grab some JSON to/from a webserver, and then call an event which bubbles up through delegates to (what will eventually be a) UI change event (at the moment it's just a debug.writeline call). 基本上,我要做的就是向Web服务器发布JSON并从Web服务器获取一些JSON,然后调用一个事件,该事件通过委托冒泡到(最终将是)UI更改事件(此刻只是一个debug.writeline)呼叫)。

I have two PCL libraries, one is the 'core' and the other is a library the core references, and a WPF app and a OS X app - the WPF app works fine. 我有两个PCL库,一个是“核心”库,另一个是核心引用库,还有一个WPF应用程序和一个OS X应用程序-WPF应用程序运行良好。 I'm also using MVVMCross. 我也在使用MVVMCross。

At first I tried using a preexisting class I had which used HTTPWebRequest, and it worked fine, for the first button click (which fires this call). 最初,我尝试使用一个预先存在的类,该类使用HTTPWebRequest,并且对于第一次单击按钮(触发此调用)的工作正常。 On the second button click the OS X app crashes. 在第二个按钮上,单击OS X应用程序崩溃。 I tried switching to HttpClient, no dice. 我尝试切换到HttpClient,没有骰子。

After reading this thread: https://bugzilla.xamarin.com/show_bug.cgi?id=19906 I tried, using interfaces switching out the HTTP class for the OS X app to the native implementation of NSUrlConnection. 阅读此线程后: https ://bugzilla.xamarin.com/show_bug.cgi?id=19906我尝试使用接口将OS X应用程序的HTTP类切换到NSUrlConnection的本机实现。

Now this is the situaiton I find myself: If I have a NSUrlConnection ASync request with an anonymous function passed to it it works forever click after click If I take that out and call a FireEvent() function which just raises events (which may raise more events down the chain) then it works forever, click after click If I have both the ASync with anonymous function and the FireEvent, on the third click of the button that fires this off, it throws a native crash. 现在,这是我发现的情况:如果我有一个传递了匿名函数的NSUrlConnection ASync请求,它将永远有效,单击后单击。如果我将其取出并调用一个FireEvent()函数,该函数只会引发事件(可能引发更多事件)事件),然后将其永久有效,请单击后单击。如果同时具有匿名功能的ASync和FireEvent,则在触发该按钮的按钮的第三次单击时,将引发本机崩溃。

If I take out all the async stuff, it will work fine, but that's not ideal. 如果我删除所有异步内容,它将可以正常工作,但这并不理想。

Any ideas? 有任何想法吗? I'm at my wits end. 我机智。

        public void ExecuteAsync() 
    {
        var request = new NSUrlRequest(new NSUrl("http://www.example.com"));

        asyncRunning = true;

        NSUrlConnection.SendAsynchronousRequest(request, NSOperationQueue.MainQueue, delegate(NSUrlResponse response, NSData data, NSError error) {

        var responseStr = data.ToString();

            var blah = new HttpResponseCompleteEventArgs("{TESTJSONThatIveRemovedForReadability}");

            System.Diagnostics.Debug.WriteLine("Inside IsMainThread: " + NSThread.IsMain.ToString());

            response.InvokeOnMainThread ( delegate {
                FireEvent(blah);
                System.Diagnostics.Debug.WriteLine("Inside IsMainThread invoke: " + NSThread.IsMain.ToString());
            });



        });

        System.Diagnostics.Debug.WriteLine("Outside IsMainThread: " + NSThread.IsMain.ToString());


    }

And the crash 和崩溃

Stacktrace:

  at <unknown> <0xffffffff>
  at (wrapper managed-to-native) MonoMac.AppKit.NSApplication.NSApplicationMain (int,string[]) <IL 0x0009d, 0xffffffff>
  at MonoMac.AppKit.NSApplication.Main (string[]) [0x00041] in /Users/builder/data/lanes/xamcore-lion-1.8-branch/b8b75fd4/source/xamcore/src/AppKit/NSApplication.cs:105
  at FreshlySqueezed.Mac.MainClass.Main (string[]) [0x00007] in /Users/blah/Development/Development/FreshlySqueezed/FreshlySqueezed.Mac/Main.cs:14
  at (wrapper runtime-invoke) <Module>.runtime_invoke_void_object (object,intptr,intptr,intptr) <IL 0x00050, 0xffffffff>

Native stacktrace:


Debug info from gdb:

^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
^D
quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quit

^D
quProcess 2693 stopped
* thread #1: tid = 0x1e2f7, 0x91b0cfed libsystem_kernel.dylib`__wait4 + 5, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
  thread #2: tid = 0x1e30e, 0x91b0d992 libsystem_kernel.dylib`kevent64 + 10, queue = 'com.apple.libdispatch-manager'
  thread #3: tid = 0x1e30f, 0x91b0d046 libsystem_kernel.dylib`__workq_kernreturn + 10
  thread #4: tid = 0x1e310, 0x91b0d046 libsystem_kernel.dylib`__workq_kernreturn + 10
  thread #5: tid = 0x1e311, 0x91b0d046 libsystem_kernel.dylib`__workq_kernreturn + 10
  thread #6: tid = 0x1e314, 0x91b07fb6 libsystem_kernel.dylib`semaphore_wait_trap + 10
  thread #7: tid = 0x1e315, 0x91b0ca26 libsystem_kernel.dylib`__recvfrom + 10
  thread #8: tid = 0x1e32c, 0x91b07f7a libsystem_kernel.dylib`mach_msg_trap + 10
  thread #9: tid = 0x1e32e, 0x91b0d046 libsystem_kernel.dylib`__workq_kernreturn + 10
(lldb) quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit

quit^D
qu* thread #1: tid = 0x1e2f7, 0x91b0cfed libsystem_kernel.dylib`__wait4 + 5, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
  * frame #0: 0x91b0cfed libsystem_kernel.dylib`__wait4 + 5
    frame #1: 0x92c46ec5 libsystem_c.dylib`waitpid$UNIX2003 + 48
    frame #2: 0x018ab5f9 libmono-2.0.dylib`mono_handle_native_sigsegv(signal=11, ctx=0x006e1fe0) + 489 at mini-exceptions.c:2305
    frame #3: 0x018fd9d5 libmono-2.0.dylib`mono_arch_handle_altstack_exception(sigctx=0x006e1fe0, fault_addr=0x608962a8, stack_ovf=0) + 149 at exceptions-x86.c:1170
    frame #4: 0x01804351 libmono-2.0.dylib`mono_sigsegv_signal_handler(_dummy=11, info=0x006e1fa0, context=0x006e1fe0) + 369 at mini.c:6842
    frame #5: 0x94fd1deb libsystem_platform.dylib`_sigtramp + 43

  thread #2: tid = 0x1e30e, 0x91b0d992 libsystem_kernel.dylib`kevent64 + 10, queue = 'com.apple.libdispatch-manager'
    frame #0: 0x91b0d992 libsystem_kernel.dylib`kevent64 + 10
    frame #1: 0x9a415899 libdispatch.dylib`_dispatch_mgr_invoke + 238
    frame #2: 0x9a415532 libdispatch.dylib`_dispatch_mgr_thread + 52

  thread #3: tid = 0x1e30f, 0x91b0d046 libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #0: 0x91b0d046 libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #1: 0x91cfbdcf libsystem_pthread.dylib`_pthread_wqthread + 372

  thread #4: tid = 0x1e310, 0x91b0d046 libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #0: 0x91b0d046 libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #1: 0x91cfbdcf libsystem_pthread.dylib`_pthread_wqthread + 372

  thread #5: tid = 0x1e311, 0x91b0d046 libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #0: 0x91b0d046 libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #1: 0x91cfbdcf libsystem_pthread.dylib`_pthread_wqthread + 372

  thread #6: tid = 0x1e314, 0x91b07fb6 libsystem_kernel.dylib`semaphore_wait_trap + 10
    frame #0: 0x91b07fb6 libsystem_kernel.dylib`semaphore_wait_trap + 10
    frame #1: 0x01a1891e libmono-2.0.dylib`mono_sem_wait(sem=<unavailable>, alertable=<unavailable>, sem=0x01b1ac20, alertable=1) + 30 at mono-semaphore.c:121
    frame #2: 0x019c43ea libmono-2.0.dylib`finalizer_thread(unused=0x00000000) + 74 at gc.c:1073
    frame #3: 0x0199c654 libmono-2.0.dylib`start_wrapper [inlined] start_wrapper_internal(data=0x00193bd0) + 442 at threads.c:647
    frame #4: 0x0199c49a libmono-2.0.dylib`start_wrapper(data=0x00193bd0) + 26 at threads.c:692
    frame #5: 0x01a1de1d libmono-2.0.dylib`inner_start_thread(arg=0xbffff2c0) + 253 at mono-threads-posix.c:94
    frame #6: 0x01a3eebd libmono-2.0.dylib`GC_start_routine(arg=0x006e2f60) + 93 at pthread_support.c:1502
    frame #7: 0x91cfa5fb libsystem_pthread.dylib`_pthread_body + 144
    frame #8: 0x91cfa485 libsystem_pthread.dylib`_pthread_start + 130

  thread #7: tid = 0x1e315, 0x91b0ca26 libsystem_kernel.dylib`__recvfrom + 10
    frame #0: 0x91b0ca26 libsystem_kernel.dylib`__recvfrom + 10
    frame #1: 0x92c470c9 libsystem_c.dylib`recv$UNIX2003 + 54
    frame #2: 0x018d58c0 libmono-2.0.dylib`socket_transport_recv(buf=0xb039aeed, len=11) + 160 at debugger-agent.c:1085
    frame #3: 0x018d1c8d libmono-2.0.dylib`debugger_thread(arg=0x00000000) + 21485 at debugger-agent.c:1475
    frame #4: 0x01a1de1d libmono-2.0.dylib`inner_start_thread(arg=0xbffff2c0) + 253 at mono-threads-posix.c:94
    frame #5: 0x01a3eebd libmono-2.0.dylib`GC_start_routine(arg=0x006e2f60) + 93 at pthread_support.c:1502
    frame #6: 0x91cfa5fb libsystem_pthread.dylib`_pthread_body + 144
    frame #7: 0x91cfa485 libsystem_pthread.dylib`_pthread_start + 130

  thread #8: tid = 0x1e32c, 0x91b07f7a libsystem_kernel.dylib`mach_msg_trap + 10
    frame #0: 0x91b07f7a libsystem_kernel.dylib`mach_msg_trap + 10
    frame #1: 0x91b0716c libsystem_kernel.dylib`mach_msg + 68
    frame #2: 0x9bea0bf9 CoreFoundation`__CFRunLoopServiceMachPort + 169
    frame #3: 0x9bea01d1 CoreFoundation`__CFRunLoopRun + 1393
    frame #4: 0x9be9f9ea CoreFoundation`CFRunLoopRunSpecific + 394
    frame #5: 0x9be9f84b CoreFoundation`CFRunLoopRunInMode + 123
    frame #6: 0x90de9b88 AppKit`_NSEventThread + 283
    frame #7: 0x91cfa5fb libsystem_pthread.dylib`_pthread_body + 144
    frame #8: 0x91cfa485 libsystem_pthread.dylib`_pthread_start + 130

  thread #9: tid = 0x1e32e, 0x91b0d046 libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #0: 0x91b0d046 libsystem_kernel.dylib`__workq_kernreturn + 10
    frame #1: 0x91cfbdcf libsystem_pthread.dylib`_pthread_wqthread + 372
Executing commands in '/tmp/mono-gdb-commands.J45EfM'.
(lldb)  process attach --pid 2693
Process 2693 stopped

Anyone got any idea? 有人知道吗? I'm stumped. 我很沮丧

Thanks 谢谢

So after hours of head scratching I seem to have stumbled across the solution. 因此,经过数小时的头部抓挠之后,我似乎偶然发现了该解决方案。

From early on I had suspicions that this had something to do with Garbage Collection, or an Event losing it's binding as the app crashes before any of my code is hit after hitting the button the third time, and from reading other stackoverflow issues with Xamarin/OS X my symptoms sounded similar to a over-eager Garbage Collector. 从一开始我就怀疑这与垃圾回收有关,或者是事件丢失了它的绑定,因为应用程序在第三次按下按钮后在我的任何代码被点击之前崩溃,并且读取了Xamarin /的其他stackoverflow问题OS X我的症状听起来像是一个急切的垃圾收集器。

So at first I thought I'd raise an event every time I get the response from the webserver and the event has bubbled up to the ViewModel, so essentially bubbling it up to the ViewController in the OSX project. 因此,起初我以为每次我从网络服务器获得响应时都会引发一个事件,并且该事件已冒泡到ViewModel,因此实际上将其冒泡到OSX项目中的ViewController。 The intention was to try and use this event to rebind the button binding after every click - however I tried running it with an empty Event Handler, and I discovered it fixed the initial issue! 目的是尝试使用此事件在每次单击后重新绑定按钮绑定-但是我尝试使用空的事件处理程序运行它,但发现它解决了最初的问题!

So despite the fact the ViewController already has a reference to the ViewModel through this.ViewModel, it seems OS X/XamMac was being over-eager and disposing of the ViewModel, therefore bringing the App to it's knees. 因此,尽管事实上ViewController已经通过this.ViewModel引用了ViewModel,但OS X / XamMac似乎过于渴望并丢弃ViewModel,因此使该应用程序屈服了。 Interestingly, I only found adding and handling an event to fix this issue, trying to assign this.ViewModel to another class variable had no effect. 有趣的是,我只发现添加并处理一个事件来解决此问题,试图将this.ViewModel分配给另一个类变量无效。

So here's the code that fixed it: 所以这是修复它的代码:

In the viewmodel I added this: 在视图模型中,我添加了以下内容:

public event System.EventHandler GoCommandFinished;

public void CallbackFromWebRequest(SqueezeBase value){
                System.Diagnostics.Debug.WriteLine("hmmm");
            Hello = "whey?" + x;
            if (GoCommandFinished != null) {
                GoCommandFinished (null, null);
            }
        }

and in the view controller on the OS X side I added this to the ViewDidLoad: 在OS X端的视图控制器中,我将此添加到了ViewDidLoad中:

((FirstViewModel)this.ViewModel).GoCommandFinished += GoCommandFinished;

and then created an empty function to handle this: 然后创建一个空函数来处理此问题:

private void GoCommandFinished(object sender, EventArgs e){

        }

And volia! 和跳! I'd be interested to know a cleaner way of sorting this out, as this feels very hacky to me... but for now, I don't care, it works! 我很想知道一种更干净的方法来解决这个问题,因为这对我来说感觉很棘手……但是就目前而言,我不在乎,它的工作原理! But if anyone from Xamarin could explain how to calm down the Garbage Collection a bit more elegantly, that would be great! 但是,如果Xamarin中的任何人都可以更优雅地解释如何使“垃圾收集”更加平静,那将是很棒的!

Thanks 谢谢

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

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