是否有将DispatchWorkItems附加到DispatchQueue的特定方法,而不是在代码中声明它们? [英] Is there a specific way to append DispatchWorkItems to a DispatchQueue instead of re declaring them in code?
问题描述
我有几个要在队列上执行的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
-in
或forEach
:
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
}
请注意,我使用了async
与sync
,因为使用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屋!