如何创建队列并手动启动它
How to create queue and start it manually
在我的应用程序中,我必须实现刷新令牌逻辑。我希望在刷新令牌过程中,所有发送的请求都保存在一个队列中,一旦我的过程完成,我就启动队列
例如,我想要这样的东西:
let queue = DispatchQueue(label: "myQueue", attributes: .concurrent)
queue.async {
// request One
}
queue.async {
// request Two
}
当刷新令牌过程完成时:
queue.send()
你可以像这样构建一个class
class ConcurrentQueue {
typealias Task = () -> ()
private var tasks: [Task] = []
private let serialQueue = DispatchQueue(label: "Serial queue")
func enqueueTask(_ task: @escaping Task) {
serialQueue.sync {
tasks.append(task)
}
}
func runAndRemoveAllTasks() {
serialQueue.sync {
tasks.forEach { task in
task()
}
tasks.removeAll()
}
}
}
这 class 允许您入队多个 Task(s)
。
Every Task is a closure like this () -> Void
.
当您将一个 Task 加入队列时,它不会被执行,它只是附加到内部数组。
看
let concurrentQueue = ConcurrentQueue()
concurrentQueue.enqueueTask {
print("1")
}
concurrentQueue.enqueueTask {
print("2")
}
concurrentQueue.enqueueTask {
print("3")
}
这段代码的结果只是保存了3个任务,它们并没有被执行。
然后当你打电话时
concurrentQueue.runAndRemoveAllTasks()
所有任务都已执行并在控制台中得到
1
2
3
线程安全
方法 enqueueTask(_)
和 runAndRemoveAllTasks()
是线程安全的。
事实上,它们仅在
内与内部 tasks
数组(不是隐式线程安全的)交互
serialQueue.sync {
...
}
这保证了对 tasks
数组的一致访问。
解决方案是使用 BlockOperation:
let pendingRequests = BlockOperation()
pendingRequests.addExecutionBlock {
//Adding first request
}
pendingRequests.addExecutionBlock {
//Adding second request
}
刷新令牌完成时:
pendingRequests.start()
In my application I have to implement a refresh token logic. I would like that during the refresh token process all requests sent be kept in a queue and as soon as my process is finished I start the queue
如果你想创建一个队列并延迟其任务的开始,只需暂停它,例如:
let queue = DispatchQueue(label: "myQueue", attributes: .concurrent)
queue.suspend()
queue.async {
// request One
}
queue.async {
// request Two
}
fetchToken { result in
switch result {
case .success(let token):
// do something with token
print(token)
queue.resume()
case .failure(let error):
// handle the error
print(error)
}
}
这就是您 suspend
and resume
调度队列的方式。请注意,suspend
仅阻止项目在队列中启动,但对已经 运行 的任务没有影响。这就是为什么我在向其发送项目之前暂停队列。
但是以上内容引出了您在 failure
场景中想要做什么的问题。你只有一个队列,里面有一堆计划好的任务。从理论上讲,您可以保留对那些分派块的引用(通过使用 DispatchWorkItem
模式而不是简单的闭包,并且您可以 cancel
这些项目),但我可能会到达一个操作队列,例如
let queue = OperationQueue()
queue.isSuspended = true
queue.addOperation {
// request One
}
queue.addOperation {
// request Two
}
fetchToken { result in
switch result {
case .success(let token):
// do something with token
print(token)
queue.isSuspended = false
case .failure(let error):
// handle the error
print(error)
queue.cancelAllOperations()
}
}
这和上面的一样,但是我们可以用cancelAllOperations
取消所有排队的操作。
顺便说一下,您可以创建自定义 Operation
子类来处理本身是异步的任务。我假设您的“请求一”和“请求二”是异步网络请求。请参阅 looking for a specific example where Operation is preferred over GCD or vice-versa 以讨论何时可能更喜欢 OperationQueue
而不是 DispatchQueue
。
在我的应用程序中,我必须实现刷新令牌逻辑。我希望在刷新令牌过程中,所有发送的请求都保存在一个队列中,一旦我的过程完成,我就启动队列
例如,我想要这样的东西:
let queue = DispatchQueue(label: "myQueue", attributes: .concurrent)
queue.async {
// request One
}
queue.async {
// request Two
}
当刷新令牌过程完成时:
queue.send()
你可以像这样构建一个class
class ConcurrentQueue {
typealias Task = () -> ()
private var tasks: [Task] = []
private let serialQueue = DispatchQueue(label: "Serial queue")
func enqueueTask(_ task: @escaping Task) {
serialQueue.sync {
tasks.append(task)
}
}
func runAndRemoveAllTasks() {
serialQueue.sync {
tasks.forEach { task in
task()
}
tasks.removeAll()
}
}
}
这 class 允许您入队多个 Task(s)
。
Every Task is a closure like this
() -> Void
.
当您将一个 Task 加入队列时,它不会被执行,它只是附加到内部数组。
看
let concurrentQueue = ConcurrentQueue()
concurrentQueue.enqueueTask {
print("1")
}
concurrentQueue.enqueueTask {
print("2")
}
concurrentQueue.enqueueTask {
print("3")
}
这段代码的结果只是保存了3个任务,它们并没有被执行。
然后当你打电话时
concurrentQueue.runAndRemoveAllTasks()
所有任务都已执行并在控制台中得到
1
2
3
线程安全
方法 enqueueTask(_)
和 runAndRemoveAllTasks()
是线程安全的。
事实上,它们仅在
内与内部tasks
数组(不是隐式线程安全的)交互
serialQueue.sync {
...
}
这保证了对 tasks
数组的一致访问。
解决方案是使用 BlockOperation:
let pendingRequests = BlockOperation()
pendingRequests.addExecutionBlock {
//Adding first request
}
pendingRequests.addExecutionBlock {
//Adding second request
}
刷新令牌完成时:
pendingRequests.start()
In my application I have to implement a refresh token logic. I would like that during the refresh token process all requests sent be kept in a queue and as soon as my process is finished I start the queue
如果你想创建一个队列并延迟其任务的开始,只需暂停它,例如:
let queue = DispatchQueue(label: "myQueue", attributes: .concurrent)
queue.suspend()
queue.async {
// request One
}
queue.async {
// request Two
}
fetchToken { result in
switch result {
case .success(let token):
// do something with token
print(token)
queue.resume()
case .failure(let error):
// handle the error
print(error)
}
}
这就是您 suspend
and resume
调度队列的方式。请注意,suspend
仅阻止项目在队列中启动,但对已经 运行 的任务没有影响。这就是为什么我在向其发送项目之前暂停队列。
但是以上内容引出了您在 failure
场景中想要做什么的问题。你只有一个队列,里面有一堆计划好的任务。从理论上讲,您可以保留对那些分派块的引用(通过使用 DispatchWorkItem
模式而不是简单的闭包,并且您可以 cancel
这些项目),但我可能会到达一个操作队列,例如
let queue = OperationQueue()
queue.isSuspended = true
queue.addOperation {
// request One
}
queue.addOperation {
// request Two
}
fetchToken { result in
switch result {
case .success(let token):
// do something with token
print(token)
queue.isSuspended = false
case .failure(let error):
// handle the error
print(error)
queue.cancelAllOperations()
}
}
这和上面的一样,但是我们可以用cancelAllOperations
取消所有排队的操作。
顺便说一下,您可以创建自定义 Operation
子类来处理本身是异步的任务。我假设您的“请求一”和“请求二”是异步网络请求。请参阅 looking for a specific example where Operation is preferred over GCD or vice-versa 以讨论何时可能更喜欢 OperationQueue
而不是 DispatchQueue
。