是否有将DispatchWorkItems附加到DispatchQueue的特定方法,而不是在代码中声明它们? [英] Is there a specific way to append DispatchWorkItems to a DispatchQueue instead of re declaring them in code?

查看:108
本文介绍了是否有将DispatchWorkItems附加到DispatchQueue的特定方法,而不是在代码中声明它们?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有几个要在队列上执行的Dispatch工作项,我不想重新声明代码,我想将它们传递给数组或DispatchWorkItems列表,然后将其注入到调度队列中,是否有任何方法要实现这一目标?

I have several Dispatch work items to execute on a queue i don't want to redeclare the codes, i want to pass them to an array or list of DispatchWorkItems and then inject it to a dispatch queue is there any way to achieve this ?

    func executeDispatchWorkItem(url: String, completion  : @escaping  (Result<String,Error>)-> Void,beganHandler  : @escaping  (String)-> Void){

do {
    beganHandler("\(url) Began to execute ")
    let content = try String(contentsOf:URL(string: url)!)
    completion(.success(content))
}
catch let error {
        completion(.failure(error))
}
sleep(1)

 }

   var serialQueue = DispatchQueue(label: "A queue")

  serialQueue.async {
executeDispatchWorkItem(url: "https://www.google.com/",completion: 
{data in

    switch data {
    case .success(let data):
        print("URL : \(data) completed  with \(String(describing: data))")
    case .failure(let error ):
        print("URL : \(error.localizedDescription) failed  with \(error.localizedDescription)")
    }

}, beganHandler: { me in
        print("\(me) began to execute ")
})

executeDispatchWorkItem(url: "www.facebook.com",completion: {data in

    switch data {
    case .success(let data):
        print("URL : \(data) completed  with \(String(describing: 
data))")
    case .failure(let error ):
        print("URL : \(error.localizedDescription) failed  with \(error.localizedDescription)")
    }

}, beganHandler: { me in
        print("\(me) began to execute ")
})
executeDispatchWorkItem(url: "www.youtube.com",completion: {data in

    switch data {
    case .success(let data):
        print("URL : \(data) completed  with \(String(describing: data))")
    case .failure(let error ):
        print("URL : \(error.localizedDescription) failed  with \(error.localizedDescription)")
    }

}, beganHandler: { me in
        print("\(me) began to execute ")
})

////我将如何实现类似的目的

/// HOW EVER I WANT TO ACHIEVE SOMETHING LIKE THIS

let itemsToExecute : [DispatchWorkItem] = [dispatch1.dispatch2]

//这可能吗?

serialQueue.sync(execute: itemsToExecute) ?

推荐答案

是的,您可以拥有一个DispatchWorkItem对象的数组,但是要分派所有对象,您只需要遍历它们即可,例如,使用for-inforEach:

Yes, you can have an array of DispatchWorkItem objects, but to dispatch them all, you’d just have to iterate through them, e.g., with either for-in or forEach:

let queue = DispatchQueue(label: "com.domain.app.requests")
let group = DispatchGroup()

let itemsToExecute: [DispatchWorkItem] = [item1, item2]

itemsToExecute.forEach { queue.async(group: group, execute: $0) }

group.notify(queue: .main) {
    print("all done")         // this is called when the requests are done
}

请注意,我使用了asyncsync,因为使用GCD的全部目的是避免阻塞主队列,而sync阻塞而async则不会.

Note, I used async vs sync, because the whole point of using GCD is to avoid blocking the main queue, and while sync blocks, async doesn’t.

这引出了一个问题,即为什么您要完全使用DispatchWorkItem数组.只需将任务直接添加到队列中,队列就会为您跟踪所有任务.

This begs the question of why you’d bother using an array of DispatchWorkItem at all, though. Just add the tasks to the queue directly, and the queue takes care of keeping track of all of them for you.

坦率地说,我们可能只想使用URLSession.例如:

Frankly, we’d probably just want to use URLSession. For example:

@discardableResult
func request(from urlString: String, completion: @escaping  (Result<String,Error>) -> Void) -> URLSessionTask {
    let task = URLSession.shared.dataTask(with: URL(string: urlString)!) { data, response, error in
        guard let data = data, error == nil else {
            completion(.failure(error!))
            return
        }

        guard
            let httpResponse = response as? HTTPURLResponse,
            200..<300 ~= httpResponse.statusCode
        else {
            completion(.failure(NetworkError.invalidResponse(data, response)))
            return
        }

        guard let string = String(data: data, encoding: .utf8) else {
            completion(.failure(NetworkError.nonStringBody))
            return
        }

        completion(.success(string))
    }
    task.resume()
    return task
}

也许在哪里:

enum NetworkError: Error {
    case invalidResponse(Data, URLResponse?)
    case nonStringBody
}

然后,您可以执行以下操作:

Then, you can do something like:

for urlString in urlStrings {
    group.enter()
    request(from: urlString) { result in
        defer { group.leave() }

        switch result {
        case .failure(let error):
            print(urlString, error)

        case .success(let string):
            print(urlString, string.count)
        }
    }
}

group.notify(queue: .main) {
    print("all done")
}

这篇关于是否有将DispatchWorkItems附加到DispatchQueue的特定方法,而不是在代码中声明它们?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆