gpt4 book ai didi

iOS URL 请求。信号量问题

转载 作者:行者123 更新时间:2023-11-30 13:18:02 25 4
gpt4 key购买 nike

我正在进入并发编程,但遇到了一些信号量问题。我的函数首先从服务器加载数据,分析接收到的信息,然后,如有必要,向服务器发出第二个请求。

我尝试了不同的方法让它运行,但没有一个做得很好。我当前的代码对我来说似乎是正确的,但在第二次请求时它只是锁定(可能像死锁)并且最后一个日志是“<__NSCFLocalDataTask:0x7ff470c58c90> {taskIdentifier:2} {暂停}”

请告诉我我不知道什么。也许有更优雅的方式来处理这些目的的完成?

提前谢谢您!

var users = [Int]()
let linkURL = URL.init(string: "https://bla bla")
let session = URLSession.shared()
let semaphore = DispatchSemaphore.init(value: 0)
let dataRequest = session.dataTask(with:linkURL!) { (data, response, error) in
let json = JSON (data: data!)
if (json["queue"]["numbers"].intValue>999) {
for i in 0...999 {
users.append(json["queue"]["values"][i].intValue)
}
for i in 1...lround(json["queue"]["numbers"].doubleValue/1000) {
let session2 = URLSession.shared()
let semaphore2 = DispatchSemaphore.init(value: 0)
let linkURL = URL.init(string: "https://bla bla")
let dataRequest2 = session2.dataTask(with:linkURL!) { (data, response, error) in
let json = JSON (data: data!)
print(i)
semaphore2.signal()
}
dataRequest2.resume()
semaphore2.wait(timeout: DispatchTime.distantFuture)
}
}
semaphore.signal()
}
dataRequest.resume()
semaphore.wait(timeout: DispatchTime.distantFuture)

附注我为什么要这样做。服务器返回有限数量的数据。为了获得更多,我必须使用偏移量。

最佳答案

这是死锁,因为您正在等待 URLSessiondelegateQueue 上的信号量。默认委托(delegate)队列不是主队列,而是一个串行后台队列(即 maxConcurrentOperationCount1OperationQueue)。因此,您的代码正在等待同一串行队列上的信号量,该队列应该向信号量发送信号。

战术修复是确保您没有在 session 的完成处理程序正在运行的同一个串行队列上调用 wait。有两个明显的修复:

  1. 不要使用共享 session (其delegateQueue是一个串行队列),而是实例化您自己的URLSession并指定其delegateQueue 是您创建的并发 OperationQueue:

    let queue = OperationQueue()
    queue.name = "com.domain.app.networkqueue"

    let configuration = URLSessionConfiguration.default()
    let session = URLSession(configuration: configuration, delegate: nil, delegateQueue: queue)
  2. 或者,您可以通过将带有信号量的代码分派(dispatch)到其他队列来解决此问题,例如

    let mainRequest = session.dataTask(with: mainUrl) { data, response, error in
    // ...
    DispatchQueue.global(attributes: .qosUserInitiated).async {
    let semaphore = DispatchSemaphore(value: 0)

    for i in 1 ... n {
    let childUrl = URL(string: "https://blabla/\(i)")!
    let childRequest = session.dataTask(with: childUrl) { data, response, error in
    // ...
    semaphore.signal()
    }
    childRequest.resume()
    _ = semaphore.wait(timeout: .distantFuture)
    }
    }
    }
    mainRequest.resume()
<小时/>

为了完整起见,我会注意到您可能根本不应该使用信号量来发出这些请求,因为您最终会因为发出一系列连续请求而付出重大的性能损失(加上您阻塞一个线程,这通常是不鼓励的)。

为了做到这一点而重构这段代码的难度更大一些。它基本上需要发出一系列并发请求,也许使用“下载”任务而不是“数据”任务来最大程度地减少内存影响,然后当所有请求完成后,根据需要将其全部拼凑在一起(由任一请求触发) 操作“完成”操作或调度组通知)。

关于iOS URL 请求。信号量问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38035430/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com