阻止当前线程,直到部分代码在iOS主线程上运行
我有一个用例,在ios中将数据写入本地couchebase数据库。这里不支持写操作的并发访问。所以我想在主线程上运行CRUD操作并在辅助线程上运行一些算法后返回结果。当主线程接管控制并执行代码时,当前正在运行的线程不会等待主线程完成其操作。我怎样才能从主线程结果切换到其他线程。阻止当前线程,直到部分代码在iOS主线程上运行
例:
+(BOOL)createDocument:(NSDictionary*)data withId:(NSString*)docId {
__block CBLDocument* doc = nil;
// NSLog(@"%d count ", [[self database] documentCount]);
dispatch_async(dispatch_get_main_queue(), ^{
if(docId.length > 0) {
doc = [[self getDatabase] documentWithID:docId];
} else {
doc = [[self getDatabase] createDocument];
}
});
//I want current thread to wait till main thread completes its execution
if(doc){
return YES;
}else{
return NO;
}
}
如果你知道一个事实,这个方法不能从主队列调用,您可以使用dispatch_sync
:
+(BOOL)createDocument:(NSDictionary*)data withId:(NSString*)docId {
__block CBLDocument* doc = nil;
dispatch_sync(dispatch_get_main_queue(), ^{
if(docId.length > 0) {
doc = [[self getDatabase] documentWithID:docId];
} else {
doc = [[self getDatabase] createDocument];
}
});
//I want current thread to wait till main thread completes its execution
if(doc){
return YES;
}else{
return NO;
}
}
一个更广义的方法是创建一个专用的,定制的调度队列为您的数据库交互。然后,任何想要与数据库交互的线程(主线程或任何后台线程)都会执行到该专用队列的dispatch_sync
。
这提供了一个更清晰的实现,使功能意图更加明确,并确保从后台线程启动的数据库交互不会阻塞主线程(当然,除非主线程恰好在启动与此数据库的交互数据库队列在同一时间)。这种专用的队列方法符合WWDC 2012 video, Asynchronous Design Patterns with Blocks, GCD, and XPC(这是视频后半部分讨论的第五种设计模式)中讨论的“每个子系统的一个队列”设计模式的精神。
你可以让另一dispatch_async
调用从主线程的 “当前线程”。所以你会使用另一个功能块,并把你的if(doc)
的东西进去。这就是使用GCD API处理线程之间的链接的方式。
所以你的代码的问题是,createDocument
分派到另一个线程后返回。相反,您应该更改createDocument
以采用功能块参数。
+(BOOL)createDocument:(NSDictionary*)data
withId:(NSString*)docId
onComplete:(void (^)(CBLDocument*))onComplete;
,改变你的dispatch_async
电话如下:
dispatch_async(dispatch_get_main_queue(), ^{
if(docId.length > 0) {
doc = [[self getDatabase] documentWithID:docId];
} else {
doc = [[self getDatabase] createDocument];
}
dispatch_async(yourCurrentThread, ^{
onComplete(doc);
});
});
但是,如果你真的想阻止你的当前线程,你应该使用dispatch_sync
而不是dispatch_async
。
dispatch_sync(dispatch_get_main_queue(), ^{
...
});
return doc != nil;
对不起,如果有任何语法错误,我还没有测试过。