0

我有使用 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 捕获的原始线程?

你对我有什么想法吗?

4

0 回答 0