为了账号安全,请及时绑定邮箱和手机立即绑定

继续 OS X - 两个库调用系统函数

继续 OS X - 两个库调用系统函数

Go
一只名叫tom的猫 2021-12-07 10:04:30
我发现至少为 Mac 编写一些具有或多或少常见 UI 的东西是很困难的。我的应用程序必须有托盘图标并且能够显示系统通知问题是 goroutine 本身。在 Mac 上对 UI 框架的任何调用都要求从主线程调用,或者至少以线程安全的方式调用。当我已经在运行 UI(嗯,对于 GUI 应用程序是必须的,不是吗?)并尝试显示通知时,就会出现问题。这样做的原因似乎是系统托盘包 Init 函数必须被锁定到主线程使用runtime.LockOsThread并且永远不会释放它。然后,如果我尝试显示也需要runtime.LockOsThread它的通知,则会导致以下错误:2016-01-11 22:56:27.973 main[30162:4094392] *** Assertion failure in +[NSUndoManager _endTopLevelGroupings], /Library/Caches/com.apple.xbs/Sources/Foundation/Foundation-1256.1/Misc.subproj/NSUndoManager.m:3592016-01-11 22:56:27.974 main[30162:4094392] +[NSUndoManager(NSInternal) _endTopLevelGroupings] is only safe to invoke on the main thread.2016-01-11 22:56:27.977 main[30162:4094392] (    0   CoreFoundation                      0x00007fff8d42bae2 __exceptionPreprocess + 178    1   libobjc.A.dylib                     0x00007fff8bb03f7e objc_exception_throw + 48    2   CoreFoundation                      0x00007fff8d42b8ba +[NSException raise:format:arguments:] + 106    3   Foundation                          0x00007fff8cb4c88c -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 198    4   Foundation                          0x00007fff8cad24c1 +[NSUndoManager(NSPrivate) _endTopLevelGroupings] + 170    5   AppKit                              0x00007fff8514206a -[NSApplication run] + 844    6   main                                0x0000000004166200 nativeLoop + 128    7   main                                0x0000000004165bca _cgo_8c6479959095_Cfunc_nativeLoop + 26    8   main                                0x000000000405a590 runtime.asmcgocall + 112)有解决方法吗?到目前为止我能想到的就是将 UI 和通知放入单独的二进制文件中,并使它们通过某种 IPC 与 main 进行通信。但我可能会遗漏一些东西。
查看完整描述

2 回答

?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

由于这个问题没有足够的吸引力,我决定发布我在尝试解决此问题时发现的自己的解决方案。这不会被标记为答案,因为其他人可能会提供更好的解决方案。

我提出UI过程中的一个(即部分使用系统托盘)到另一个二进制和使用调用它cmd := exec.Command(...)cmd.Start()后来我管stdin,并stdout与那些通过这个子进程进行通信。

示例代码可以在Github上找到。警告在这个要点中有一个错误,在子进程退出后,主进程将开始消耗 CPU 周期。随意自己修复它。

我不想通过 RPC 的原因是因为这对于我想要实现的目标来说会变得有点过于复杂,并且没有提供简单的方法来进行双向通信。


查看完整回答
反对 回复 2021-12-07
?
慕田峪7331174

TA贡献1828条经验 获得超13个赞

看起来您使用的两个库都正确用于runtime.LockOSThread进行仅主线程 API 调用;不幸的是,要使用多个这样的库,您必须做一些比提供的示例代码更有趣的事情。您需要编写自己的主线程/main.Main调用消息循环来处理对多个 MTO API 的调用。

runtime.LockOSThread是使用此类 API 进行操作的解决方案的一部分;golang wiki有一个关于如何使用它与“仅从主线程调用”API 交互的页面

关于你的程序应该如何改变的极短的描述:

您需要使用runtime.LockOSThreadinmain.init来确保主线程正在运行main.Mainmain.Main应该重构为两部分:

  1. 启动一个 goroutine 或 goroutines 运行之前的内容main.Main

  2. 进入消息循环接收消息以在一个或多个通道上执行某些主线程操作


查看完整回答
反对 回复 2021-12-07
  • 2 回答
  • 0 关注
  • 131 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信