Objective-c 验证当前执行线程,以防万一,在正确的线程中重新执行该方法

Objective-c verify the current execution thread and, in case, re execute the method in the correct thread

我正在尝试创建一个方法来检查当前线程是什么,如果它与所需线程不同,则在正确的线程中重新执行(调用者)方法。

我正在使用:

-(void)aMethod:(id)aParam
{
   [self executeInRightThread];
   ...
}

这是当前代码:

-(void)executeInRightThread
{
    NSString * rightQueueLabel = [NSString stringWithCString:dispatch_queue_get_label(myQueue) encoding:NSUTF8StringEncoding];
    NSString * currentQueueLabel = [NSString stringWithCString:dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) encoding:NSUTF8StringEncoding];
    BOOL isInTheRightQueue = [currentQueueLabel isEqualToString:rightQueueLabel];

    NSString *sourceString = [[NSThread callStackSymbols] objectAtIndex:1]; // Example: 1   UIKit 0x00540c89 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1163
    NSCharacterSet *separatorSet = [NSCharacterSet characterSetWithCharactersInString:@" -[]+?.,"];
    NSMutableArray *array = [NSMutableArray arrayWithArray:[sourceString  componentsSeparatedByCharactersInSet:separatorSet]];
    [array removeObject:@""];

//    NSLog(@"Stack = %@", [array objectAtIndex:0]);
//    NSLog(@"Framework = %@", [array objectAtIndex:1]);
//    NSLog(@"Memory address = %@", [array objectAtIndex:2]);
//    NSLog(@"Class caller = %@", [array objectAtIndex:3]);
//    NSLog(@"Function caller = %@", [array objectAtIndex:4]);
//    NSLog(@"Line caller = %@", [array objectAtIndex:5]);
    NSString * callerMethodName = [array objectAtIndex:4];

    if ( !isInTheRightQueue )
    {
        dispatch_async(myQueue, ^{
            [self performSelector:NSSelectorFromString(callerMethodName)];
        });
    }
}

executeInRightThread 方法运行良好,但我不知道如何检索调用方方法参数(示例中的 aParam),我不想将参数传递给 executeInRightThread 方法, 主要目的是创建无处不在的东西,不使用块也不传递不同的参数。

使用NSThread currentThread查询当前线程。但是,您的问题有点混乱,因为您随后指定了变量 isInTheRightQueue

您无法查询当前队列 - dispatch_get_current_queue() 已被弃用,并且不会总是 return 您所期望的(并且 dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) 有完全相同的问题)。我们 运行 在 iOS 8 上遇到了一个案例,其中 AVCaptureVideoOutput 配置为在主队列上回调我们。在回调中,我们发现dispatch_get_current_queue()的return结果不是我们预期的(我们原来调用setSampleBufferDelegate:... queue:dispatch_get_main_queue(),而是:

(lldb) po dispatch_get_current_queue()
<OS_dispatch_queue: com.apple.avfoundation.videodataoutput.bufferqueue[0x170118e40] = { xrefcnt = 0x1, refcnt = 0x3, suspend_cnt = 0x0, locked = 1, target = com.apple.main-thread[0x1001be800], width = 0x0, running = 0x0, barrier = 1 }>
(lldb) p  (char*)dispatch_queue_get_label(nil)
(char *)  = 0x000000017026f8c0 "com.apple.avfoundation.videodataoutput.bufferqueue"
(lldb) p (char*)dispatch_queue_get_label((dispatch_queue_t)[captureOutput sampleBufferCallbackQueue])
(char *)  = 0x00000001001af6b0 "com.apple.main-thread"

请注意,这是一个针对主线程的队列,而不是主队列本身。

队列和线程之间没有映射关系。任何在后台线程上执行的队列——与主线程相反——都可以在任何后台线程上执行。

您想要检查执行线程的正常情况是您是否需要执行影响 UI.

的代码
if(![NSThread isMainThread])
{
    dispatch_sync(dispatch_get_main_queue(), ^{ .... });
}

如果您需要验证您是否已在正确的后台队列上被回调,那么您可能需要更清楚地考虑您的应用程序逻辑。但是,如果你真的需要这样做,为什么不对相关的后台队列做一个dispatch_async。这将延迟执行您想要的任务,但由于您已经在后台,这可能无关紧要。