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。这将延迟执行您想要的任务,但由于您已经在后台,这可能无关紧要。
我正在尝试创建一个方法来检查当前线程是什么,如果它与所需线程不同,则在正确的线程中重新执行(调用者)方法。
我正在使用:
-(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。这将延迟执行您想要的任务,但由于您已经在后台,这可能无关紧要。