自定义异步 NSApplication 事件循环导致随机崩溃

Custom async NSApplication event loop causes random crashes

提问人:Nelson Yeung 提问时间:11/15/2023 更新时间:11/15/2023 访问量:29

问:

以下代码启动一个空白的 GUI 应用程序,但在单击关闭和单击窗口时,它会随机崩溃。通过 Xcode 运行它有时会在崩溃时显示,但并非总是如此。No error handler for XPC error: <private>

我通过使用使事件循环异步。如果删除 await,应用程序将不会崩溃。await Task.yield()

将循环转换为异步的原因是我想在 CLI 工具的异步函数中启动一个 GUI。我可以通过编译一个单独的可执行文件来轻松解决这个问题,该可执行文件在单独的进程中启动 GUI,这样我就不需要异步了,但我想简化构建,只想知道为什么会发生这种情况。

创建一个并使用以下命令运行:foo.swift./foo.swift

#!/usr/bin/env swift
import AppKit
import Foundation

class AppDelegate: NSObject, NSApplicationDelegate {}

let app = NSApplication.shared
let appDelegate = AppDelegate()
NSWindow(
  contentRect: NSRect(x: 0, y: 0, width: 640, height: 400),
  styleMask: [.closable, .miniaturizable, .titled],
  backing: .buffered,
  defer: true
).makeKeyAndOrderFront(nil)
app.delegate = appDelegate
app.setActivationPolicy(.regular)
app.finishLaunching()
while true {
  if let ev = app.nextEvent(
    matching: .any, until: .distantFuture, inMode: .default, dequeue: true
  ) {
    app.sendEvent(ev)
  }
  await Task.yield()  // This is causing random crashes
}
Swift macOS 异步等待

评论

1赞 Alexander 11/15/2023
这不是在 AppKit 中创建事件循环的方式。请参阅 RunLoop。您只需将自己的源/事件排队到实际的运行循环中即可。
0赞 Nelson Yeung 11/15/2023
@Alexander我从 stackoverflow.com/a/48023455/2687427 和 GLFW repo github.com/glfw/glfw/blob/ 那里得到这个......但无论哪种方式,如果您知道为什么在添加时会导致随机崩溃,请将其作为答案提交。await Task.yield()
0赞 Alexander 11/15/2023
是的。。。。这似乎很粗略。在不知道 RunLoop 还做了什么(从它的源代码来看)的情况下,我们怎么能知道这个手动重新实现是否遗漏了什么?您在这里看到的可能是主线程、主运行循环和主任务执行器之间的一些交互。如果你要喊的任务正在等待某个东西在运行循环上运行,那么你就会陷入僵局。不过,不知道为什么它会崩溃。
0赞 Alexander 11/15/2023
我们需要更详细地了解您到底想通过这里实现什么,然后才能提出任何特定的解决方案Task.yield()
0赞 Nelson Yeung 11/15/2023
是的,我同意;我真的希望我们能完全实现 ,然后人们可以更容易地覆盖它。Tbh,我并不是真的在这里寻找解决方案,它更像是一个理论问题。我有一个解决方案,只是想知道为什么。尽管如此,我在尝试以编程方式在方法中创建 GUI 时发现了这一点。我正在尝试异步,然后制作了一个启动 GUI 和 VM 的异步函数。虚拟机从未启动,因为我意识到 while 循环阻止了它。NSApplication.runAsyncArgumentParser.runVZVirtualMachine.start

答: 暂无答案