我有一个用例,我将数据写入ios中的本地couchebase数据库。这里它不支持写操作的并发访问。所以我想在主线程上运行CRUD操作,并在对辅助线程上的数据运行一些算法后返回结果。当主线程接管控制并执行代码时,当前运行的线程不等待主线程完成其操作。如何将结果从主线程切换到其他线程。
前:
+(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;
}
}
答案 0 :(得分:2)
如果你知道这个方法没有从主队列中调用,你可以使用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中讨论的设计模式(它是视频后半部分讨论的第五种设计模式)。
答案 1 :(得分:0)
您可以从主线程对您的“当前主题”进行另一次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;
对不起,如果有任何语法错误,我还没有测试过。