Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 是否获取当前调度队列?_Iphone_Ios_Objective C_Grand Central Dispatch_Dispatch - Fatal编程技术网

Iphone 是否获取当前调度队列?

Iphone 是否获取当前调度队列?,iphone,ios,objective-c,grand-central-dispatch,dispatch,Iphone,Ios,Objective C,Grand Central Dispatch,Dispatch,我有一个方法,它应该支持从任何队列调用,并且应该期望 它在后台线程本身运行一些代码,然后在向其块参数返回值时使用dispatch\u get\u main\u queue 我不希望它在进入方法时将其强制到主队列中。是否有方法获取指向当前调度队列的指针?您可以选择,但是iOS 6.1 SDK使用以下免责声明定义了此API: “建议仅用于调试和记录目的:” 及 “此函数已弃用,将在将来的版本中删除。” 你可以考虑如果代码是未来的证明。 不赞成 DeXCHOGGETHORTENTHORE()/Code

我有一个方法,它应该支持从任何队列调用,并且应该期望

它在后台线程本身运行一些代码,然后在向其块参数返回值时使用
dispatch\u get\u main\u queue

我不希望它在进入方法时将其强制到主队列中。是否有方法获取指向当前调度队列的指针?

您可以选择,但是iOS 6.1 SDK使用以下免责声明定义了此API:

建议仅用于调试和记录目的:

此函数已弃用,将在将来的版本中删除。


你可以考虑如果代码是未来的证明。

不赞成<代码> DeXCHOGGETHORTENTHORE()/Code >实际上无法知道你正在执行什么队列。如果仔细阅读,您最终会发现这是因为“我在执行哪个队列?”(因为队列最终指向一个全局队列,等等)的问题可能有多个答案

如果要保证将来的块在特定队列上运行,那么唯一的方法是让API接受队列作为参数与完成块一起使用。这使调用方可以决定在何处执行完成


如果仅仅知道调用者是否在主线程上就足够了,那么可以使用
+[NSThread isMainThread]
来查找。在常见情况下,在主GCD队列上执行的所有块都将在主线程上执行。(此规则的一个例外是,如果应用程序使用
dispatch\u main()
代替主运行循环,则必须使用
dispatch\u get\u specific
和friends来确定您正在主队列上执行,这是一种相对罕见的情况。)更常见的情况是,注意,并非所有在主线程上执行的代码都通过GCD在主队列上执行;GCD从属于主线程runloop。对于您的特定情况,这听起来可能就足够了。

如果您使用的是
NSOperationQueue
,它可以为您提供当前调度队列

NSOperationQueue具有类函数
[NSOperationQueue currentQueue]
,该函数将当前队列作为NSOperationQueue对象返回。要获取调度队列对象,可以使用
[NSOperationQueue currentQueue].underyingQueue
,它将当前队列作为
调度队列返回

Swift 3:

if let currentDispatch = OperationQueue.current?.underlyingQueue {
    print(currentDispatch)
}

-为主队工作

不推荐使用
dispatch\u get\u current\u queue()
您无法直接获取指向正在运行的队列的指针,但是您可以通过调用
dispatch\u queue\u get\u label(dispatch\u current\u queue\u label)
来获取当前队列的标签,这确实给了您一些灵活性

您总是可以通过比较它们的标签来检查您是否在该特定队列上,因此在您的情况下,如果您不想将其强制在主队列上,当您输入该方法时,您可以使用以下标志:

let isOnMainQueue = (dispatch_queue_get_label(dispatch_get_main_queue()) == dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL))
如果您在全局队列上运行,您将获得与其QOS类型相关联的队列标签,该标签可以是以下之一:

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\u get\u global\u queue(qos\u class\u self(),0)
,它将返回您正在运行的同一个全局队列


但我认为苹果特别不鼓励我们将逻辑绑定到我们被调用的队列,因此更好地将其用于专门的调试目的。

作为此
NSOBject
方法的替代方法,在当前线程的运行循环上调度调用。根据文件:

此方法设置一个计时器,以便在服务器上执行aSelector消息 当前线程的运行循环

很明显,我建议使用延迟为零的方法,根据文档再次说明:

指定延迟为0并不一定会导致选择程序失败 立即执行。选择器仍在线程的 运行循环并尽快执行

不幸的是,它只需要一个参数,所以如果您的方法或多或少需要一些变通方法

我注意到的另一件事是,这种方法不适用于协议,而只适用于实现。这是因为此方法存在于
NSObject
类别中,而不在
NSObject
界面中(请参见下面的PS)。可以通过强制转换为
id
轻松解决此问题

PS:存在两个不同的
NSObject
s,一个协议和一个实现。注意
NSObject
声明:

@interface NSObject <NSObject> { ... }
@interface-NSObject{…}

这可能看起来很奇怪,但一个正在声明(在
@interface
之后),另一个是先前声明的协议(在
之间)。当声明扩展NSObject的协议(即,
@protocol Foo
)时,该协议继承了后者的方法,而不是前者。最终,协议由继承自
NSObject
实现的某个类实现,因此继承自
NSObject
实现的所有实例仍然有效。但我已经离题了。

实际上还有一种方法可以比较队列

设置队列时,请确保添加了标签。出于我的目的,我有一个共享队列,用于访问数据库以防止数据库锁定。在我的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事务队列在文件中本地使用,以将所有执行分派到数据库。但是,它还有一个公共访问器,允许将整个事务分派到数据库。因此,在内部,如果从事务队列中调用DB访问方法,我们需要在d上进行内部调度
/**
 * @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);
// 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();
}
let queueName = dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)
class Worker {
    private static let queueKey = DispatchSpecificKey<Int>()
    private lazy var queueContext = unsafeBitCast(self, to: Int.self)
    private lazy var queue: DispatchQueue = {
        let value = DispatchQueue(label: "com.example.App.Worker")
        value.setSpecific(key: Worker.queueKey, value: queueContext)
        return value
    }()

    func test(x: Int) -> Int {
        return dispatchSync {
            return x > 2 ? test(x: x - 1) * x : x
        }
    }

    private func dispatchSync<T>(_ block: () throws -> T) rethrows -> T {
        if DispatchQueue.getSpecific(key: Worker.queueKey) != queueContext {
            return try queue.sync(execute: block)
        }
        return try block()
    }
}

let worker = Worker()
worker.test(x: 5)
import Foundation

// MARK: private functionality

extension DispatchQueue {

    private struct QueueReference { weak var queue: DispatchQueue? }

    private static let key: DispatchSpecificKey<QueueReference> = {
        let key = DispatchSpecificKey<QueueReference>()
        setupSystemQueuesDetection(key: key)
        return key
    }()

    private static func _registerDetection(of queues: [DispatchQueue], key: DispatchSpecificKey<QueueReference>) {
        queues.forEach { $0.setSpecific(key: key, value: QueueReference(queue: $0)) }
    }

    private static func setupSystemQueuesDetection(key: DispatchSpecificKey<QueueReference>) {
        let queues: [DispatchQueue] = [
                                        .main,
                                        .global(qos: .background),
                                        .global(qos: .default),
                                        .global(qos: .unspecified),
                                        .global(qos: .userInitiated),
                                        .global(qos: .userInteractive),
                                        .global(qos: .utility)
                                    ]
        _registerDetection(of: queues, key: key)
    }
}

// MARK: public functionality

extension DispatchQueue {
    static func registerDetection(of queue: DispatchQueue) {
        _registerDetection(of: [queue], key: key)
    }

    static var currentQueueLabel: String? { current?.label }
    static var current: DispatchQueue? { getSpecific(key: key)?.queue }
}
DispatchQueue.currentQueueLabel
DispatchQueue.current
DispatchQueue.global(qos: .default) == DispatchQueue.current
DispatchQueue.main === DispatchQueue.current
let queue = DispatchQueue(label: "queue-sample")
DispatchQueue.registerDetection(of: queue)
if DispatchQueue.current == queue { ... }
func subTest(queue: DispatchQueue) {
    queue.async {
        print("--------------------------------------------------------")
        print("queue label: \(DispatchQueue.currentQueueLabel ?? "nil")")
        print("print DispatchQueue.current: \(String(describing: DispatchQueue.current))")
        print("print queue == DispatchQueue.current: \(queue == DispatchQueue.current)")
        print("print queue === DispatchQueue.current: \(queue === DispatchQueue.current)")
        print("DispatchQueue.main == DispatchQueue.current: \(DispatchQueue.main == DispatchQueue.current)\n")
    }
}

func test() {
    subTest(queue: DispatchQueue.main)
    sleep(1)
    subTest(queue: DispatchQueue.global(qos: .default))
    sleep(1)
    subTest(queue: DispatchQueue.global(qos: .utility))
    sleep(1)

    let queue = DispatchQueue(label: "queue-sample")
    DispatchQueue.registerDetection(of: queue)
    subTest(queue: queue)
    sleep(1)
}

test()
DispatchQueue.global(qos: .default).async {
    test()
}
--------------------------------------------------------
queue label: com.apple.root.default-qos
print DispatchQueue.current: Optional(<OS_dispatch_queue_global: com.apple.root.default-qos[0x7fff89eb47c0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = [0x0], width = 0xfff, state = 0x0060000000000000, in-barrier}>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: false

--------------------------------------------------------
queue label: com.apple.root.utility-qos
print DispatchQueue.current: Optional(<OS_dispatch_queue_global: com.apple.root.utility-qos[0x7fff89eb46c0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = [0x0], width = 0xfff, state = 0x0060000000000000, in-barrier}>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: false

--------------------------------------------------------
queue label: queue-sample
print DispatchQueue.current: Optional(<OS_dispatch_queue_serial: queue-sample[0x600000275780] = { xref = 7, ref = 3, sref = 2, target = com.apple.root.default-qos.overcommit[0x7fff89eb4840], width = 0x1, state = 0x0060002500000b01, enqueued, max qos 5, draining on 0xb03, in-barrier}>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: false

--------------------------------------------------------
queue label: com.apple.main-thread
print DispatchQueue.current: Optional(<OS_dispatch_queue_main: com.apple.main-thread[0x7fff89eb43c0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = com.apple.root.default-qos.overcommit[0x7fff89eb4840], width = 0x1, state = 0x001ffe9000000300, dirty, in-flight = 0, thread = 0x303 }>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: true

--------------------------------------------------------
queue label: com.apple.main-thread
print DispatchQueue.current: Optional(<OS_dispatch_queue_main: com.apple.main-thread[0x7fff89eb43c0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = com.apple.root.default-qos.overcommit[0x7fff89eb4840], width = 0x1, state = 0x001ffe9000000300, dirty, in-flight = 0, thread = 0x303 }>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: true

--------------------------------------------------------
queue label: com.apple.root.default-qos
print DispatchQueue.current: Optional(<OS_dispatch_queue_global: com.apple.root.default-qos[0x7fff89eb47c0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = [0x0], width = 0xfff, state = 0x0060000000000000, in-barrier}>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: false

--------------------------------------------------------
queue label: com.apple.root.utility-qos
print DispatchQueue.current: Optional(<OS_dispatch_queue_global: com.apple.root.utility-qos[0x7fff89eb46c0] = { xref = -2147483648, ref = -2147483648, sref = 1, target = [0x0], width = 0xfff, state = 0x0060000000000000, in-barrier}>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: false

--------------------------------------------------------
queue label: queue-sample
print DispatchQueue.current: Optional(<OS_dispatch_queue_serial: queue-sample[0x60000027a280] = { xref = 7, ref = 3, sref = 2, target = com.apple.root.default-qos.overcommit[0x7fff89eb4840], width = 0x1, state = 0x0060002500000b01, enqueued, max qos 5, draining on 0xb03, in-barrier}>)
print queue == DispatchQueue.current: true
print queue === DispatchQueue.current: true
DispatchQueue.main == DispatchQueue.current: false