Swift Actor 挂起 - 异步调用后未返回对执行的控制

问题描述 投票:0回答:1

当我尝试调用另一个静态异步函数并声明在主要参与者上运行时,我的参与者遇到了问题。具体来说,被调用函数执行到最后,但似乎永远不会将执行控制权返回给调用者(我的演员)。

这导致函数调用后的代码永远不会执行。

简单来说,看起来正在执行的 MainThread 只是简单地“吞噬”了 return 语句。

下面是我的代码(结构上)的一个最小示例。在被调用函数中实际发生的是

ScreenCaptureKit
调用。为了清楚起见,我决定把它们留在里面。

actor SomeActor {
  func myTestFunction() async throws {
    print("Before execution")
    let returnValue = try await SomeClass.createSCKSnapshot()
    print("After execution") // this is never called since the previous await never seems to return execution back to SomeActor
  }
}

@MainActor
class SomeClass {
  @MainActor public static func createSCKSnapshot() async throws -> (displays: [SCDisplay], windows: [SCWindow], applications: [SCRunningApplication]) {
    let shareableContent: SCShareableContent = try await SCShareableContent.excludingDesktopWindows(false, onScreenWindowsOnly: false)

    return (shareableContent.displays, shareableContent.windows, shareableContent.applications)
  }
}

现在,在这里你看到我的演员

SomeActor
试图在它的一个孤立函数中调用
SomeClass.createSCKSnapshot()
。因此,
createSCKSnapshot()
执行得很好,包括 return 语句,但是没有任何反应并且
print("After execution")
永远不会在
SomeActor
.

中执行

为什么?以及如何绕过这个问题并确保我的程序在

createSCKSnapshot()
返回后继续正常执行?

编辑:

应用程序确实有权限并在应用程序的各个位置使用ScreenCaptureKit,一切正常。唯一的区别是来自这些位置的代码不是从 actor 内部调用方法,而是从类中调用方法。因此,我相信这一定是演员的某种问题。

swift actor swift-concurrency
1个回答
0
投票

考虑:

func myTestFunction() async throws {
    print("Before execution")
    let returnValue = try await SomeClass.createSCKSnapshot()
    print("After execution")
}

有两种可能:

  1. 第一次尝试此操作时,

    SCShareableContent.excludingDesktopWindows
    将暂停,直到用户响应系统对话消息。

  2. 如果用户拒绝许可,应用程序的后续启动将不会导致看到“执行后”消息(更不用说屏幕录制弹出消息)。将抛出一个错误,并且在

    try
    行之后什么也不会执行。第二个
    print
    声明将无法实现(尽管
    myTestFunction
    会返回)。


FWIW,在边缘情况下(我在 Ventura 13.3.1 中遇到过,但无法重现)

excludingDesktopWindows
暂停,但它的延续永远不会恢复。没有线程/actors 被阻塞,但是在
await
之后,它永远不会继续执行。这种奇怪的行为似乎已通过重新启动我的计算机(!)得到解决。

© www.soinside.com 2019 - 2024. All rights reserved.