有没有一种特定的方法可以将 DispatchWorkItems 附加到 DispatchQueue 而不是在代码中重新声明它们?
Is there a specific way to append DispatchWorkItems to a DispatchQueue instead of re declaring them in code?
我有几个 Dispatch 工作项要在队列上执行我不想重新声明代码,我想将它们传递给 DispatchWorkItems
的数组或列表,然后将其注入调度队列有什么办法可以做到这一点吗?
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 ")
})
/// 我多么想实现这样的目标
let itemsToExecute : [DispatchWorkItem] = [dispatch1.dispatch2]
// 这可能吗?
serialQueue.sync(execute: itemsToExecute) ?
是的,你可以有一个 DispatchWorkItem
对象数组,但要分派它们,你只需要遍历它们,例如,使用 for
-in
或 forEach
:
let queue = DispatchQueue(label: "com.domain.app.requests")
let group = DispatchGroup()
let itemsToExecute: [DispatchWorkItem] = [item1, item2]
itemsToExecute.forEach { queue.async(group: group, execute: [=10=]) }
group.notify(queue: .main) {
print("all done") // this is called when the requests are done
}
注意,我使用 async
与 sync
,因为使用 GCD 的全部意义在于避免阻塞主队列,而 sync
阻塞时,async
没有。
不过,这引出了一个问题,即为什么您会费心使用 DispatchWorkItem
的数组。只需将任务直接添加到队列中,队列就会为您跟踪所有任务。
坦率地说,我们可能只想使用 URLSession
。例如:
@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
}
然后,您可以执行以下操作:
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")
}
我有几个 Dispatch 工作项要在队列上执行我不想重新声明代码,我想将它们传递给 DispatchWorkItems
的数组或列表,然后将其注入调度队列有什么办法可以做到这一点吗?
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 ")
})
/// 我多么想实现这样的目标
let itemsToExecute : [DispatchWorkItem] = [dispatch1.dispatch2]
// 这可能吗?
serialQueue.sync(execute: itemsToExecute) ?
是的,你可以有一个 DispatchWorkItem
对象数组,但要分派它们,你只需要遍历它们,例如,使用 for
-in
或 forEach
:
let queue = DispatchQueue(label: "com.domain.app.requests")
let group = DispatchGroup()
let itemsToExecute: [DispatchWorkItem] = [item1, item2]
itemsToExecute.forEach { queue.async(group: group, execute: [=10=]) }
group.notify(queue: .main) {
print("all done") // this is called when the requests are done
}
注意,我使用 async
与 sync
,因为使用 GCD 的全部意义在于避免阻塞主队列,而 sync
阻塞时,async
没有。
不过,这引出了一个问题,即为什么您会费心使用 DispatchWorkItem
的数组。只需将任务直接添加到队列中,队列就会为您跟踪所有任务。
坦率地说,我们可能只想使用 URLSession
。例如:
@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
}
然后,您可以执行以下操作:
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")
}