处理阻塞、完成处理程序、dispatch_async与dispatch_sync的区别

4

我正在一个线程中执行在线获取数据的操作,我想在这个块被执行后立即执行一些操作。

这是我的代码:

- (IBAction)refresh:(UIBarButtonItem *)sender {
    NSLog(@"checking");
    [self editToolbar];
    dispatch_queue_t fetchQ = dispatch_queue_create("Refreshing", NULL);
    dispatch_async(fetchQ, ^{
        [self setupFetchedResultsController];
        [self fetchImonggoItemsDataIntoDocument: self.itemDatabase];
    });
    dispatch_release(fetchQ); 

    NSLog(@"done checking");
    //do something here
}

问题在于dispatch_async立即返回,“done checking”立即打印,甚至在块执行完成之前。我该如何解决这个问题?


3
为什么不把你想做的事情放在区块末尾?我是否误解了你的问题? - jscs
1
问题在于 performBlock: 是否立即返回(异步运行)?只要在后台线程上,总是可以使用 performBlockAndWait: - gregheo
@acecapades 我觉得你需要调试你的代码,然后找出控制返回的确切点!! - aks.knit1108
@acecapades 请尝试以下链接:https://dev59.com/vnA75IYBdhLWcg3wSm64https://dev59.com/4l7Va4cB1Zd3GeqPMrwj - aks.knit1108
尝试使用dispatch_sync替换dispatch_async。 - aks.knit1108
谢谢@Amit,我尝试了那个方法,但还是不行。还是谢谢。 - acecapades
2个回答

4
我认为这是一个建筑问题。任务如下:
1. 编辑工具栏 2. 将Imonggo项目数据提取到文档中 3. 做一些其他事情
如果这些任务必须按照顺序执行,那么我不太明白使用块或队列的用途;只需按顺序运行语句即可。
否则,替代方案#1是使用`dispatch_sync`而不是`dispatch_async`。同样,我不太确定使用队列的好处是什么,但它确实存在。
替代方案#2是从块中使用回调。类似于:
- (IBAction)refresh:(UIBarButtonItem *)sender {
    NSLog(@"checking");
    [self editToolbar];
    dispatch_queue_t fetchQ = dispatch_queue_create("Refreshing", NULL);
    dispatch_async(fetchQ, ^{
        [self setupFetchedResultsController];
        [self fetchImonggoItemsDataIntoDocument: self.itemDatabase];
        [self doneChecking]; // <-- NOTE! call the callback
    });
    dispatch_release(fetchQ); 
}

// NOTE! refresh: has been split up into two methods
- (void)doneChecking:
    NSLog(@"done checking");
    //do something here
}

还可以使用dispatch_async将另一个块加入队列来执行回调操作,但实际上没有理由不按照你在这里编写的方式进行操作。(我甚至不明白为什么会有这个问题...) - jscs
值得指出的是,如果doneChecking将要操作任何UI元素,那么它应该在主线程中完成,而不是在fetchQ中完成。使用另一个调度调用,但只请求主队列。 - Joey J

1

正如其他人已经建议的那样,这可能是你需要的。

NSArray *items = [iMonggoFetcher fetchImonggoData:IMONGGO_GENERIC_URL_FOR_PRODUCTS withFormat:@"json" withDateRangeArgs:args];
[document.managedObjectContext performBlock:^{
    for (NSDictionary *itemInfo in items){
        [Product productWithImonggoInfo:itemInfo inManagedObjectContext:document.managedObjectContext];
    }
    // Put here what you need :)
}];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接