获取当前的调度队列?
我有一个应该支持从任何队列中调用的方法,并且应该期望。 它在后台线程本身中运行一些代码,然后在返回值为block参数时使用dispatch_get_main_queue。 如果不是当它进入方法时,我不希望它强制进入主队列。 有没有办法获得一个指向当前调度队列的指针?
您可以select“ dispatch_get_current_queue()
” ,但是iOS 6.1 SDK使用以下免责声明来定义此API:
“ Recommended for debugging and logging purposes only:
”
和
“ This function is deprecated and will be removed in a future release.
”
这是另一个相关的问题,你可以考虑一些替代scheme ,如果你想要的代码是未来的certificate。
由于dispatch_get_current_queue()
的弃用,实际上没有办法知道你正在执行什么队列。 如果您仔细阅读GCD源文件 ,您最终会看到这是因为对于“我在执行什么队列?”这个问题可能有多个答案。 (因为队列最终瞄准全球队列之一等)
如果要保证在特定队列上运行将来的块,唯一的方法是让API作为参数接受队列以及完成块。 这可以让调用者决定完成的地方。
如果简单地知道调用者是否在主线程上就够了,可以用+[NSThread isMainThread]
来查找。 在一般情况下,主GCD队列上执行的所有块将在主线程上执行。 (这个规则的一个例外是,如果你的应用程序使用dispatch_main()
代替主运行循环,你将不得不使用dispatch_get_specific
和好友来确定你正在主队列中执行 – 这是一个比较less见的情况)更常见的是,并不是所有在主线程上执行的代码都通过GCD在主队列上执行; GCD从属于主线程runloop。 对于你的具体情况,这听起来可能就足够了。
你可以使用NSOperationQueue。 NSOperationQueue具有类函数[NSOperationQueue currentQueue]
,它将当前队列作为NSOperationQueue对象返回。 要获得调度队列对象,你可以使用[NSOperationQueue currentQueue].underlyingQueue
,它以dispatch_queue_t
forms返回你的当前队列。
Swift 3:
if let currentDispatch = OperationQueue.current?.underlyingQueue { print(currentDispatch) }
– 为主队列工作!
通过dispatch_get_current_queue()
的弃用,你不能直接得到你正在运行的队列的指针,但是你可以通过调用dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)
获得当前队列的标签 ,这样做会给你一些灵活性。
你可以随时通过比较标签来检查你是否在特定的队列中,所以在你的情况下,如果你不想强制在主队列上,当你input方法时,你可以使用下面的标志:
let isOnMainQueue = (dispatch_queue_get_label(dispatch_get_main_queue()) == dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL))
如果您在全局队列上运行,则会恭喜地获取与其QOStypes关联的队列标签,该标签可以是以下之一:
com.apple.root.user-interactive-qos //qos_class_t(rawValue: 33) com.apple.root.user-initiated-qos //qos_class_t(rawValue: 25) com.apple.root.default-qos //qos_class_t(rawValue: 21) com.apple.root.utility-qos //qos_class_t(rawValue: 17) com.apple.root.background-qos //qos_class_t(rawValue: 9)
然后你可以使用dispatch_get_global_queue(qos_class_self(), 0)
,这会让你回到你正在运行的全局队列。
但是我相信苹果公司特别不鼓励我们将逻辑限制在我们所要求的队列中,所以更好地利用这个专门的debugging目的。
作为NSOBject
方法的替代方法performSelector:withObject:afterDelay:调用当前线程运行循环的调用。 根据文件:
这个方法设置一个定时器来在当前线程的运行循环中执行aSelector消息。
显然我build议使用这个延迟零,这再次根据文档:
指定延迟0不一定会导致select器立即执行。 select器仍在线程的运行循环中排队,并尽快执行。
不幸的是,它只需要一个参数,所以如果您的方法需要更多或更less,可能需要一些解决方法。
我注意到的另一件事是,这种方法不适用于协议,而是单独实现。 这是由于这种方法生活在一个NSObject
类别,而不是在NSObject
接口(见下面的PS)。 这可以很容易地通过铸造到id
。
PS:存在两个不同的NSObject
,一个协议和一个实现。 通知NSObject
声明:
@interface NSObject <NSObject> { ... }
这可能看起来很奇怪,但是有一个是在@interface
之后声明的,另外一个是之前声明的协议(在<
和>
之间)。 当声明一个扩展NSObject的协议(即, @protocol Foo <NSObject>
)时,协议从后者inheritance,而不是前者。 最终协议是由一些inheritance自NSObject
实现的类实现的,所以从NSObject
实现inheritance的所有实例仍然成立。 但是我正在下主题。
实际上还有一种方法来比较队列。
设置队列时,请确保添加标签。 出于我的目的,我有一个共享队列,用于访问数据库,以防止数据库locking。 在我的DB.m文件中,我已经定义了如下的共享队列函数:
const char *kTransactionQueueLabel = "DB_TRANSACTION_DISPATCH_QUEUE"; + (dispatch_queue_t)sharedDBTransactionQueue { static dispatch_queue_t sharedDBQueue = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ sharedDBQueue = dispatch_queue_create(kTransactionQueueLabel, DISPATCH_QUEUE_SERIAL); }); return sharedDBQueue; }
共享数据库事务队列在文件本地使用,以分派所有执行到数据库。 但是,也有一个公共访问器允许将整个事务分发到数据库。 所以在内部,如果从事务队列中调用DB访问方法,则需要在不同的队列(所有同步调度)上进行内部调度。 所以在内部,我总是使用下面的getter来调度适当的队列。
/** * @description Decide which queue to use - if we are already in a transaction, use the internal access queue, otherwise use the shared transaction queue. */ - (dispatch_queue_t)getProperQueueForExecution { const char *currentLabel = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL); dispatch_queue_t sharedAccessQueue = [DB sharedDBTransactionQueue]; if (strcmp(currentLabel, kTransactionQueueLabel) == 0) { sharedAccessQueue = [DB sharedInternalDBAccessQueue]; } return sharedAccessQueue; }
希望这有助于。 对不起,很长的例子。 它的要点就是你可以使用
const char *currentLabel = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL);
获取当前队列的标签并与定义的标签进行比较。
我有相同的function要求,原来的职位提到。 您应该可以在任何队列上调用此asynchronous函数,但是如果在主队列上调用该函数,则callback到主队列上的用户。 我只是这样处理它:
// cache value for if we should callback on main queue BOOL callbackOnMT = [NSThread isMainThread]; // ... // ... do async work... // ... if (callbackOnMT && ![NSThread isMainThread]){ dispatch_async(dispatch_get_main_queue(), ^{ // callback to user on main queue // as they called this function on main queue callbackToUser(); }); } else{ // callback to user on our current queue // as they called this function on a non-main queue callbackToUser(); }