英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论