2014-09-20 55 views
1

我有一个用例,在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; 
    } 
} 

回答

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(这是视频后半部分讨论的第五种设计模式)中讨论的“每个子系统的一个队列”设计模式的精神。

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; 

对不起,如果有任何语法错误,我还没有测试过。

相关问题