我正在尝试创建一个方法来检查当前线程是什么,如果它与所需的线程不同,请在右侧线程中重新执行(调用方)方法。
我正在使用:
-(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
方法,主要目标是创建可在任何地方使用的东西,不使用块而不传递不同的参数。
答案 0 :(得分:3)
使用NSThread currentThread
查询当前线程。但是,您的问题有点困惑,因为您随后指定了变量isInTheRightQueue
。
您无法查询当前队列 - dispatch_get_current_queue()
已弃用,并且不会始终返回您期望的内容(并且dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL)
具有完全相同的问题)。我们在iOS 8上遇到了一个案例,其中AVCaptureVideoOutput被配置为在主队列上回调我们。在回调中,我们发现dispatch_get_current_queue()
的返回结果与我们预期的不同(我们最初称为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 *) $4 = 0x000000017026f8c0 "com.apple.avfoundation.videodataoutput.bufferqueue"
(lldb) p (char*)dispatch_queue_get_label((dispatch_queue_t)[captureOutput sampleBufferCallbackQueue])
(char *) $6 = 0x00000001001af6b0 "com.apple.main-thread"
请注意,这是一个以主线程为目标的队列,而不是主队列本身。
队列和线程之间没有映射。在后台线程上执行的任何队列 - 与主线程相反 - 都可以在任何后台线程上执行。
您要检查执行线程的正常情况是您是否需要执行影响UI的代码。
if(![NSThread isMainThread])
{
dispatch_sync(dispatch_get_main_queue(), ^{ .... });
}
如果您需要验证是否已在正确的后台队列中回调,那么您可能需要更清楚地思考应用程序逻辑。但是,如果您确实需要这样做,为什么不对相关的后台队列执行dispatch_async。这将延迟执行您想要的任务,但由于您已经在后台,这可能并不重要。