dispatch_async并在原始队列上调用完成处理程序

我见过一些相关的问题,但似乎没有回答这个问题。 我想写一个方法,将在后台做一些工作。 我需要这个方法来调用原始方法调用的同一个线程/队列上的完成callback。

- (void)someMethod:(void (^)(BOOL result))completionHandler { dispatch_queue_t current_queue = // ??? // some setup code here dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ BOOL ok = // some result // do some long running processing here dispatch_async(current_queue, ^{ completionHandler(ok); }); }); 

在这里需要什么魔法咒语,所以在调用sameMethod的同一队列或线程上调用完成处理程序? 我不想承担主线。 当然, dispatch_get_current_queue不会被使用。

如果你看看苹果文档,看起来有两种模式。

如果假定完成处理程序要在主线程上运行,则不需要提供队列。 一个例子是UIViewanimations方法:

 + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion 

否则,API通常会要求调用者提供一个队列:

 [foo doSomethingWithCompletion:completion targetQueue:yourQueue]; 

我的build议是遵循这个模式。 如果不清楚应该调用完成处理程序的哪个队列,则调用程序应该明确地将其作为参数提供。

你不能真的使用队列,因为除了主队列之外,它们都不能保证在任何特定的线程上运行。 相反,你必须得到线程,并直接在那里执行你的块。

适应Mike Ash的Block Additions :

 // The last public superclass of Blocks is NSObject @implementation NSObject (rmaddy_CompletionHandler) - (void)rmaddy_callBlockWithBOOL: (NSNumber *)b { BOOL ok = [b boolValue]; void (^completionHandler)(BOOL result) = (id)self; completionHandler(ok); } @end 

 - (void)someMethod:(void (^)(BOOL result))completionHandler { NSThread * origThread = [NSThread currentThread]; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ BOOL ok = // some result // do some long running processing here // Check that there was not a nil handler passed. if( completionHandler ){ // This assumes ARC. If no ARC, copy and autorelease the Block. [completionHandler performSelector:@selector(rmaddy_callBlockWithBOOL:) onThread:origThread withObject:@(ok) // or [NSNumber numberWithBool:ok] waitUntilDone:NO]; } }); }); 

尽pipe你没有使用dispatch_async() ,但是对于程序的其余部分来说,它仍然是asynchronous的,因为它包含在原来的调度任务块中, waitUntilDone:NO也使得它与之相asynchronous。

不知道这是否会解决问题,但如何使用NSOperations而不是GCD?

 - (void)someMethod:(void (^)(BOOL result))completionHandler { NSOperationQueue *current_queue = [NSOperationQueue currentQueue]; // some setup code here NSOperationQueue *q = [[NSOperationQueue alloc] init]; [q addOperationWithBlock:^{ BOOL ok = YES;// some result // do some long running processing here [current_queue addOperationWithBlock:^{ completionHandler(ok); }]; }]; 

我想在某个队列上执行一些任务,然后像@rmaddy提到的那样执行完成块。 我遇到了来自苹果公司的并发编程指南,并实现了这一点(dispatch_retain&dispatch_released注释掉,因为我使用ARC) – https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues /OperationQueues.html#//apple_ref/doc/uid/TP40008091-CH102-SW1

 void average_async(int *data, size_t len, dispatch_queue_t queue, void (^block)(int)) { // Retain the queue provided by the user to make // sure it does not disappear before the completion // block can be called. //dispatch_retain(queue); // comment out if use ARC // Do the work on user-provided queue dispatch_async(queue, ^{ int avg = average(data, len); dispatch_async(queue, ^{ block(avg);}); // Release the user-provided queue when done //dispatch_release(queue); // comment out if use ARC }); }