我需要支持取消一个返回可以在初始化后被取消的对象的函数。在我的情况下,
requester
类在一个我无法修改的第三方库中。actor MyActor {
...
func doSomething() async throws -> ResultData {
var requestHandle: Handle?
return try await withTaskCancellationHandler {
requestHandle?.cancel() // COMPILE ERROR: "Reference to captured var 'requestHandle' in concurrently-executing code"
} operation: {
return try await withCheckedThrowingContinuation{ continuation in
requestHandle = requester.start() { result, error in
if let error = error
continuation.resume(throwing: error)
} else {
let myResultData = ResultData(result)
continuation.resume(returning: myResultData)
}
}
}
}
}
...
}
我查看了其他SO问题和该帖子:https://forums.swift.org/t/how-to-use-withtaskcancellationhandler-properly/54341/4
有些情况非常相似,但还不完全相同。这段代码无法编译,因为出现了以下错误:
"Reference to captured var 'requestHandle' in concurrently-executing code"
我猜测编译器试图保护我免受在初始化之前使用requestHandle
的影响,但我不确定如何解决这个问题。Swift论坛讨论线程中显示的其他示例似乎都有一个模式,在调用其start
函数之前可以初始化requester
对象。
我还尝试将requestHandle
保存为类变量,但在同一位置收到了不同的编译错误:
Actor-isolated property 'profileHandle' can not be referenced from a Sendable closure
doSomething
函数已经在一个actor
中,我尝试做类似于您建议的事情(我更新了问题)。但是看起来用Task{ await requestHandle?.cancel() }
包装取消处理块是关键。顺便说一下,如果我在withCheckedThrowingContinuation
闭包的主体中删除Task
包装,它也可以编译通过 - 所以不确定这是否对您的修复至关重要?还没有测试它是否支持取消或经受得住压力测试。甚至不确定如何为此编写单元测试。 - DanielwithCheckedThrowingContinuation
体中的Task
包装器仅在介绍单独的本地Actor变量以同步取消处理程序时才需要。 - Rob