我有使用 SwiftUI 编码的 iOS 应用程序。部分代码来自 Kotlin multiplatform (kmm) 我需要对异步代码做一些工作,它必须在单独的线程中执行。但我也有回调要在线程执行期间运行并且回调失败,因为可变性限制(kotlin 防止对象从一个线程共享到另一个线程)任务是逐行通过 url 读取文件。并向回调对象发送线路问题是回调对象是在外部创建的。
代码与此类似
class URlDownloadWithCallback {
let callback: DataDownloadProgressBar
init(cb:DataDownloadProgressBar) {
self.callback = cb
}
func download(url:String) {
let semaphore = DispatchSemaphore(value: 0)
Task {
defer {
semaphore.signal()
}
do {
let (bytes, response) = try await URLSession.shared.bytes(from: URL(string: url)!)
guard let httpResponse = response as? HTTPURLResponse else {
self.callback.OnFail(reason: "Failed to get http response code")
return
}
var size:Int64 = 0
if let sizeStr = httpResponse.value(forHTTPHeaderField: "X-Lines-Count") {
size = Int64(sizeStr) ?? 0
}
self.callback.OnStart(totalLines: size)
for try await line in bytes.lines {
//print(line)
self.callback.LineReceive(data: line)
}
self.callback.OnSuccess()
} catch {
//print("Error: \(error)")
self.callback.OnFail(reason: "\(error)")
}
}
semaphore.wait(timeout: .distantFuture)
}
}
我启动新线程 Thread {},当我执行 self.callback.OnStart(totalLines: size) 时出现错误“未捕获的 Kotlin 异常:kotlin.native.IncorrectDereferenceException:非法尝试访问非共享”
我不能冻结那个对象,因为它里面有一些计数器,它必须是可变的。
所以,我的问题是:有没有办法在“外部线程”中执行我的回调调用?在我在函数中调用 Thread {} 之前处于活动状态的线程中。
注意,我在这里使用 Thread 只是因为 URLSession.shared.bytes 是异步的,并且需要在线程中运行。无论如何,我调用线程并等待信号量。
在调用 Thread {} 之前,可能类似于 let originalThread = Thread.current 。然后以某种方式使用该值访问前一个线程?
另外,我知道 DispatchQueue 。但我不知道我的函数是否是从主 swift 线程调用的,所以我不会尝试执行 DispatchQueue.main.async { } 因为原始线程可能不同。也许 DispatchQueue 可以用于我用 Thread.current 捕获的原始线程?
你对我有什么想法吗?