Swift Actor挂起 – 在异步调用后没有返回执行控制

huangapple go评论57阅读模式
英文:

Swift Actor Hanging - Control over execution not returned after async call

问题

I am experiencing an issue with my actor when I am trying to call another async function that is static and declared to run on the main-actor. Specifically, the called function executes to the end, but never seems to return control over execution to the caller (my actor).

This results in the code after the function call to never be executed.

In simple terms, it looks like the executing MainThread simply "swallows" the return statement.

Below is a minimal example of what my code (structurally) looks like. What actually happens in the called function are ScreenCaptureKit calls. I decided to leave them in for clarity.

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)
  }
}

Now, here you see my actor SomeActor trying to call SomeClass.createSCKSnapshot() in one of its isolated functions. Thereby, createSCKSnapshot() executes just fine, including the return statement, but then nothing happens, and the print("After execution") is never executed inside SomeActor.

Why is that? And how can I bypass this issue and ensure that my program continues execution normally after createSCKSnapshot() returns?

EDIT:

The app does have permission and uses ScreenCaptureKit throughout various locations in the app, where everything works fine. The only difference is that code from those locations doesn't call the method from inside an actor but from a class. Therefore, I believe it must be some sort of issue with actors.

英文:

I am experiencing an issue with my actor when I am trying to call another async function that is static and declared to run on the main-actor. Specifically, the called function executes to the end, but never seems to return control over execution to the caller (my actor).

This results in the code after the function call to never be executed.

In simple terms, it looks like the executing MainThread simply "swallows" the return statement.

Below is a minimal example of what my code (structurally) looks like. What actually happens in the called function are ScreenCaptureKit calls. I decided to leave them in for clarity.

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)
  }
}

Now, here you see my actor SomeActor trying to call SomeClass.createSCKSnapshot() in one of its isolated functions. Thereby, createSCKSnapshot() executes just fine including the return statement, but then nothing happens and the print("After execution") is never executed inside SomeActor.

Why is that? And how can I bypass this issue and ensure that my program continues execution normally after createSCKSnapshot() returns?

EDIT:

The app does have permission and uses ScreenCaptureKit throughout various locations in the app, where everything works fine. The only difference is that code from those locations doesn't call the method from inside an actor but from a class. Therefore, I believe it must be some sort of issue with actors.

答案1

得分: 1

问题出现是因为我的角色上有阻塞代码,从未释放角色。因此,函数一直在队列内等待角色释放,但这从未发生。

如果您遇到类似问题,请使用Xcode Instruments来分析您的应用程序,并使用“Swift并发”模式查看在角色上执行了什么工作,以及在角色队列中等待的工作。

英文:

The issue arises because there turned out to be blocking code on my actor, never freeing up the actor. Thereby, the function was waiting inside the queue for the actor to free up, which never happened.

If you run in a similar issue, use Xcode Instruments to profile your app and use the "Swift Concurrency" mode to see what work is executed on actors, and what work is waiting in an actor's queue.

huangapple
  • 本文由 发表于 2023年4月17日 18:33:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/76034210.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定