ios 如何停止/取消/暂停/恢复 GCD 队列上的任务

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29492707/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 05:32:33  来源:igfitidea点击:

How to stop/cancel/suspend/resume tasks on GCD queue

iosqueuegrand-central-dispatch

提问by lakshmanbob

How to stop/cancel/suspend/resume tasks on GCD queue

如何停止/取消/暂停/恢复 GCD 队列上的任务

How does one stop background queue operations? I want to stop some screens in our app. And some screens it should be auto resume. So, how does one pass a queue in iOS?

如何一站式后台队列操作?我想在我们的应用程序中停止一些屏幕。有些屏幕应该是自动恢复。那么,如何在 iOS 中传递队列呢?

I mean when user have browsing the app time we run the background thread in dispatch_queue_t. But it never stops and resume in the code. So how does one suspend and resume a queue

我的意思是当用户浏览应用程序时,我们在 dispatch_queue_t 中运行后台线程。但它永远不会停止并在代码中恢复。那么如何暂停和恢复队列

回答by Rob

To suspend a dispatch queue, it's simply dispatch_suspend(queue)in Objective-C or Swift 2.3, or queue.suspend()in Swift 3. That doesn't affect any tasks currently running, but merely prevents new tasks from starting on that queue. Also, you obviously only suspend queues that you created (not global queues, not main queue).

要暂停调度队列,只需dispatch_suspend(queue)在 Objective-C 或 Swift 2.3 或queue.suspend()Swift 3 中即可。这不会影响当前正在运行的任何任务,而只是阻止新任务在该队列上启动。此外,您显然只挂起您创建的队列(不是全局队列,不是主队列)。

To resume a dispatch queue, it's dispatch_resume(queue)in Objective-C or Swift 2.3, or queue.resume()in Swift 3. There's no concept of "auto resume", so you'd just have to manually resume it when appropriate.

要恢复调度队列,它dispatch_resume(queue)在 Objective-C 或 Swift 2.3 或queue.resume()Swift 3 中。没有“自动恢复”的概念,所以你只需要在适当的时候手动恢复它。

To pass a dispatch queue around, you simply pass the dispatch_queue_tobject that you created when you called dispatch_queue_create()in Objective-C or Swift 2.3, or, in Swift 3, the DispatchQueueobject you create with DispatchQueue(label:).

要传递调度队列,只需传递在 Objective-C 或 Swift 2.3 中dispatch_queue_t调用时创建的对象dispatch_queue_create(),或者在 Swift 3 中传递DispatchQueue使用DispatchQueue(label:).

In terms of canceling tasks queued on dispatch queues, this is a new feature of iOS 8 and you'd call dispatch_block_cancel(block)with your dispatch_block_tobject in Objective-C or Swift 2.3, or item.cancel()of a DispatchWorkItemin Swift 3. This cancels queued blocks/items that have not started, but does not stop ones that are underway. If you want to be able to interrupt a dispatched block/item, you have to periodically examine dispatch_block_testcancel()in Objective-C and Swift 2.3, or item.isCancelledin Swift 3.

在排队的调度队列取消任务而言,这是针对iOS 8的新功能,你会叫dispatch_block_cancel(block)dispatch_block_t在Objective-C或雨燕2.3的对象,或者item.cancel()一个DispatchWorkItem在斯威夫特3.这将取消排队块/项没有开始了,但不会停止正在进行的。如果您希望能够中断已调度的块/项目,则必须dispatch_block_testcancel()在 Objective-C 和 Swift 2.3 或item.isCancelledSwift 3 中定期检查。

The canceling of GCD blocks is sufficiently complicated that I might refer you to the WWDC 2014 video Power, Performance and Diagnostics: What's new in GCD and XPC, which introduces you to the concept of dispatch block objects, queuing them, canceling them, etc. While this is describing the older Objective-C and Swift 2.3 API, all of the concepts are equally applicable to the newer Swift 3 API.

GCD 块的取消非常复杂,我可能会向您推荐 WWDC 2014 视频电源、性能和诊断:GCD 和 XPC 中的新内容,它向您介绍了调度块对象、排队它们、取消它们等的概念。虽然这是描述较旧的 Objective-C 和 Swift 2.3 API,但所有概念都同样适用于较新的 Swift 3 API。

If you want to cancel tasks, you might also consider using operation queues, NSOperationQueuein Objective-C or Swift 2.3, a.k.a. OperationQueuein Swift 3, as its cancelable operations have been around for a while and you're likely to find lots of examples online. It also supports constraining the degree of concurrency with maxConcurrentOperationCount(whereas with dispatch queues you can only choose between serial and concurrent, and controlling concurrency more than that requires a tiny bit of effort on your part).

如果你想取消任务,你也可以考虑使用操作队列,NSOperationQueue在 Objective-C 或 Swift 2.3 中,也就是OperationQueue在 Swift 3 中,因为它的可取消操作已经存在一段时间了,你可能会在网上找到很多例子。它还支持限制并发程度maxConcurrentOperationCount(而对于调度队列,您只能在串行和并发之间进行选择,并且控制并发不止需要您付出一点努力)。

If using operation queues, you suspend and resume by changing the suspendedproperty of the queue. And to pass it around, you just pass the NSOperationQueueobject you instantiated.

如果使用操作队列,您可以通过更改suspended队列的属性来暂停和恢复。为了传递它,您只需传递NSOperationQueue您实例化的对象。



Having said all of that, I'd suggest you expand your question to elaborate what sort of tasks are running in the background and articulate why you want to suspend them. There might be better approaches than suspending the background queue.

说了这么多,我建议你扩展你的问题,详细说明在后台运行什么样的任务,并阐明你为什么要暂停它们。可能有比暂停后台队列更好的方法。



In your comments, you mention that you were using NSTimer, a.k.a. Timerin Swift 3. If you want to stop a timer, call timer.invalidate()to stop it. Create a new NSTimerwhen you want to start it again.

在您的评论中,您提到您正在使用NSTimer,也就是Timer在 Swift 3 中。如果您想停止计时器,请调用timer.invalidate()以停止它。NSTimer当你想重新开始时创建一个新的。

Or if the timer is really running on a background thread, GCD timers do this far more gracefully, avoiding the silliness of needing to create a runloop on a background thread, which you need to run NSTimeron background threads. With a GCD timer, you can suspend/resume it just like you suspend/resume a queue, just using the timer object instead of the queue object.

或者,如果计时器真的在后台线程上运行,GCD 计时器会更优雅地执行此操作,避免需要NSTimer在后台线程上创建 runloop 的愚蠢行为,而您需要在后台线程上运行。使用 GCD 计时器,您可以像暂停/恢复队列一样暂停/恢复它,只需使用计时器对象而不是队列对象。

回答by Wain

You can't pause / cancel when using a GCD queue. If you need that functionality (and in a lot of general cases even if you don't) you should be using the higher level API - NSOperationQueue. This is built on top of GCD but it gives you the ability to control how many things are executing at the same time, suspend processing of the queue and to cancel individual / all operations.

使用 GCD 队列时不能暂停/取消。如果您需要该功能(并且在很多一般情况下,即使您不需要),您应该使用更高级别的 API - NSOperationQueue. 这是建立在 GCD 之上的,但它使您能够控制同时执行的事情的数量,暂停队列的处理并取消单个/所有操作。