Swift 串行 DispatchQueue 不串行执行

问题描述 投票:0回答:1

嘿,在我的代码中,函数“sendRequest”被多次调用,它向服务器发送请求。服务器一个接一个地处理所有请求并发回多个响应。现在我想在函数“handleResponse”中处理这些响应,但在串行队列中。所以 handleResponse 只会同时被调用一次。但是现在我的日志看起来像这样:

[15.05.2023 11:28:00.711] DEBUG NetworkDataHandler:52 - start handleResponse
[15.05.2023 11:28:00.710] DEBUG NetworkDataHandler:52 - start handleResponse
[15.05.2023 11:28:00.713] DEBUG NetworkDataHandler:52 - start handleResponse
[15.05.2023 11:28:00.713] DEBUG NetworkDataHandler:52 - start handleResponse
[15.05.2023 11:28:00.714] DEBUG NetworkDataHandler:52 - start handleResponse
...

handleResponse 因此被多次调用,尽管它还没有完成。我怎样才能让回调连续工作?

简化代码:

func sendRequest() { // is called several times
    applicationNetworkManager().sendQuery(
        ...
        successHandler: { response in
 
            let workItem = DispatchWorkItem {
                self!.handleResponse(response: response)
            }
            let serialQueue = DispatchQueue(label: "serialQueue", qos: .background)
            serialQueue.async(execute: workItem)
        }
    )
}

func handleResponse(response: Response) {
    Logger.d("start handleResponse")

    // do some stuff and write response data to local storage

    DispatchQueue.main.async {
        // update ui
    }

    Logger.d("end handleResponse")
}


swift grand-central-dispatch dispatch-async dispatch-queue
1个回答
1
投票

sendRequest
中,您每次调用
let serialQueue = DispatchQueue(label: "serialQueue", qos: .background)
时都会创建一个新的调度队列。尽管所有队列实例都具有相同的标签,但它们是不同的队列。

你没有展示你是如何创建包含

sendRequest
的类的,所以我不确定这个类是否有一个实例或者你是否有多个实例。

也最好避免

.background
QoS;在低功耗情况下,此 QoS 级别可能会导致 CPU 饥饿。
.utility
是个不错的选择

假设你有一个实例,你会使用类似的东西:

class NetworkHandler {

    let myQueue: DispatchQueue

    init() {
        self.myQueue = DispatchQueue(label:"serialQueue", qos: .utility, target: .global(qos:.utility))
    }
}

然后您可以在处理程序中使用此队列。

请注意,将您的队列定位到全局队列之一以最小化线程创建是个好主意。

© www.soinside.com 2019 - 2024. All rights reserved.