在代码中创建MenuItem时崩溃(MonoMac)

本文关键字:崩溃 MonoMac MenuItem 代码 创建 | 更新日期: 2023-09-27 18:28:45

我正在尝试在运行时动态地将一些菜单项添加到子菜单中。我可以很好地添加NSMenuItem,它就会显示出来。但是,如果我试图添加一个事件处理程序,无论是直接作为构造函数的参数,还是通过将其分配给Activated事件,我都会崩溃。菜单和子菜单是在Xcode中创建的。我只是在运行时在一个特定的子菜单中添加/删除项目。

绘制子菜单时会发生崩溃。我右键单击,将鼠标移动到上下文菜单上,直到找到动态子菜单所在的项目,然后崩溃!

坠机报告很长,但我认为最相关的部分是:

Thread 1 (process 6706):
#0  0x94f73095 in __wait4 ()
#1  0x9928699a in waitpid$UNIX2003 ()
#2  0x004a7d22 in mono_handle_native_sigsegv (signal=11, ctx=0xf6fe0) at mini-exceptions.c:2344
#3  0x004f7645 in mono_arch_handle_altstack_exception (sigctx=0xf6fe0, fault_addr=0xc8080824, stack_ovf=0) at exceptions-x86.c:1135
#4  0x00404061 in mono_sigsegv_signal_handler (_dummy=11, info=0xf6fa0, context=0xf6fe0) at mini.c:6556
#5  <signal handler called>
#6  0x98a83a8b in objc_msgSend ()
#7  0xbfffd920 in ?? ()
#8  0x9730c963 in -[NSCarbonMenuImpl _carbonUpdateStatusEvent:handlerCallRef:] ()
#9  0x973086ee in NSSLMMenuEventHandler ()
#10 0x908f79bb in _InvokeEventHandlerUPP ()
#11 0x9077f394 in DispatchEventToHandlers ()
#12 0x9077e780 in SendEventToEventTargetInternal ()
#13 0x90792655 in SendEventToEventTarget ()
#14 0x908f786a in SendHICommandEvent ()
#15 0x907535f0 in UpdateHICommandStatusWithCachedEvent ()
#16 0x9077abe2 in HIApplication::EventHandler ()
#17 0x908f79bb in _InvokeEventHandlerUPP ()
#18 0x9077f394 in DispatchEventToHandlers ()
#19 0x9077e780 in SendEventToEventTargetInternal ()
#20 0x90792655 in SendEventToEventTarget ()
#21 0x90943054 in SendMenuOpening ()
#22 0x90752dfd in DrawTheMenu ()
#23 0x90945779 in OpenSubmenu ()
#24 0x90752427 in TrackMenuCommon ()
#25 0x9094490d in PopUpMenuSelectCore ()
#26 0x909441e2 in _HandlePopUpMenuSelection7 ()
#27 0x97398295 in _NSSLMPopUpCarbonMenu3 ()
#28 0x973971b1 in -[NSCarbonMenuImpl _popUpContextMenu:withEvent:forView:withFont:] ()
#29 0x97515063 in -[NSMenu _popUpContextMenu:withEvent:forView:withFont:] ()
#30 0x97514f56 in -[NSMenu _popUpContextMenu:withEvent:forView:] ()
#31 0x97515390 in -[NSMenu _popUpMenuWithEvent:forView:] ()
#32 0x9771af45 in -[NSView rightMouseDown:] ()
#33 0x973ed635 in -[NSControl _rightMouseUpOrDown:] ()
#34 0x973ed69f in -[NSControl rightMouseDown:] ()
#35 0x971c8af1 in -[NSWindow sendEvent:] ()
#36 0x971c390f in -[NSApplication sendEvent:] ()
#37 0x970dd62c in -[NSApplication run] ()
#38 0x970805f6 in NSApplicationMain ()
#39 0x06de146b in ?? ()
#40 0x06de1290 in ?? ()
#41 0x000befe4 in ?? ()
#42 0x000bf12f in ?? ()
#43 0x0040dc05 in mono_jit_runtime_invoke (method=0x9e8c1c, obj=0x0, params=0xbffff468, exc=0x0) at mini.c:6438
#44 0x005c49ae in mono_runtime_invoke (method=0x9e8c1c, obj=0x0, params=0xbffff468, exc=0x0) at object.c:2827
#45 0x005c8dc4 in mono_runtime_exec_main (method=0x9e8c1c, args=0xe7f30, exc=0x0) at object.c:4054
#46 0x005c9135 in mono_runtime_run_main (method=0x9e8c1c, argc=0, argv=0x168d18, exc=0x0) at object.c:3678
#47 0x00478685 in mono_jit_exec (domain=0x94e00, assembly=0x1833b0, argc=2, argv=0x168d18) at driver.c:955
#48 0x0047abbf in mono_main (argc=4, argv=0x168d10) at driver.c:1014
#49 0x0000308f in main ()

我正在运行Xamarin Studio 4.0.12、Mono 3.2.0、Xcode 4.6.3、Xamarin.Mac 1.4.8、OS X 10.8.4

在代码中创建MenuItem时崩溃(MonoMac)

我希望我们的经验能有所启发。虽然没有任何代码,但这相当困难。

Mac在从c类型中抽象出这些东西方面做得非常出色。然而,有一件事是无法避免的,那就是每个操作系统(尤其是窗口系统)时间绘制事件和资源保留的方式非常不同。

特别是使用Cocoa Controller风格的窗口,内存中总是被引用的项目被清理的风险要大得多,因为Cocoa似乎更喜欢切换Windows/控制器并再次补水。

Tl;DR

  1. 保留对菜单项的模块化引用-将它们存储在控制器上的字段中。否则,它们可能会被收集起来
  2. 在执行重新绘制之前,请确保没有循环引用(由于Cocoa习惯于在属于对象的代理中定义行为,这比Windows容易得多)
  3. 删除菜单项必须从头至尾(记住,删除时计数会减少)

我们通常发现,这种神秘的崩溃是由于控件消失和/或代理引用了引用该代理的对象。

我相信有了更多的代码,我可以帮助更多!

CHeersian

我想我实际上已经发现了问题。当我删除所有涉及Properties.Settings内容的代码时,崩溃似乎完全消失了。此类继承自System.Configuration.ApplicationSettingsBase。你可以在这里看到整个班级:https://code.google.com/p/yet-another-music-application/source/browse/trunk/Player/Core/Properties/Settings.Designer.cs?r=1838

这可能是我的错,因为我采用了这种简单的持久存储方法,并使用它运行得比预期的更远。因此,我的解决方案是转而使用SQLite,这可能会在更多方面为我服务,而不仅仅是防止这些崩溃。

在任何情况下,崩溃似乎都是随机的。这可能是因为对这个类的访问主要是从不同的线程完成的。

无论如何,我确信这种组合是致命的。删除其中一个(事件处理程序或ApplicationSettingsBase)将删除崩溃。