【问题标题】:GCD going back to main threadGCD 回到主线程
【发布时间】:2012-04-06 04:52:11
【问题描述】:

在我的应用程序中,我使用 NSXMLParser 从几个 (6-10) 个网站加载信息,然后将信息加载到视图中。

现在,我的应用程序已设置好,以便在我的主视图控制器中循环遍历 viewDidLoad 中的站点,并将它们分别加载到我创建的后台线程中。它在后台线程中执行此操作,因此用户不必在视图加载之前等待所有站点加载。

for (NSMutableDictionary *dict in self.sitesArray) {
    SiteData *data = [[SiteData alloc] init];
    [data setDelegate:self];
    dispatch_async(backgroundQueue, ^(void) {
        [data loadSite:[dict objectForKey:@"SiteName"]];
    });

}

在 SiteData 中,我使用 NSXMLParser 加载站点(所有委托方法也正确实现)

-(void)loadSite:(NSString *)site{
    NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:[self fullURLForSiteName:site]];
    [parser setDelegate:self];
    [parser parse];
    return;
}

当 NSXMLParser 完成文档并且 SiteData 实例填充了站点数据时,它会将自身传递给主线程上我的主视图控制器中的方法。

- (void)parserDidEndDocument:(NSXMLParser *)parser{    
    dispatch_async(dispatch_get_main_queue(), ^(void) {
         [delegate successfullyLoadedSite:self];
    });
}

successfullyLoadedSite: 将传递的站点数据加载到视图中并将其显示给用户。请注意,多个站点的数据会显示在同一屏幕上。

我想要发生的事情:我希望每个站点的数据在加载时都显示在屏幕上,而不必等到所有站点都完成加载才能刷新视图。

发生了什么:其中一个网站加载并显示,然后我必须等待所有其他网站加载完毕,然后所有其他网站立即显示。

从控制台日志看来,一旦它第一次在主队列上调用successfullyLoadedSite:,一切都会在主队列上运行。一旦主队列上的第一个 successfullyLoadedSite: 被调用,它会将所有站点加载到对象中,然后将它们加载到视图中。

有什么想法吗?如果你不能告诉我是多线程的新手。谢谢:)


编辑: 我这样创建backgroundQueue

dispatch_queue_t backgroundQueue;

init

backgroundQueue = dispatch_queue_create("uni.que.identifier.bgqueue", NULL);

并在dealloc 中发布它:

dispatch_release(backgroundQueue);

【问题讨论】:

  • 你的意思是loadSite:第一次在后台线程上执行,然后总是在主线程上执行? backgroundQueue 是串行队列吗?你能展示你是如何创造它的吗?你曾经摧毁过它吗?
  • @Costique 我将该信息附加到我的问题中。抱歉,我不知道它是否是串行队列,但我相信你能分辨出来。我几乎可以肯定loadSite: 第一次在后台线程上执行,然后总是在主线程上执行,但我并不肯定。有什么方法可以检查吗?谢谢。
  • 所以调度队列不是串行的。将NSLog(@"%s", [NSThread isMainThread] ? "main thread" : "background thread"); 放入loadSite: 以确保它在后台正常执行。什么时候释放调度队列?

标签: objective-c ios multithreading nsxmlparser grand-central-dispatch


【解决方案1】:

使用dispatch_queue_create函数创建的队列是串行队列, 然后 dispatch_queue_create 提交的块将按顺序执行。

使用:

dispatch_queue_t backgroundQueue =
    dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

【讨论】:

  • 您的建议似乎正在发挥作用......在主线程上完成的所有事情都会同时被调用,但我认为这只是因为所有网站都在同一时间完成加载.谢谢!!
猜你喜欢
  • 1970-01-01
  • 2011-08-05
  • 1970-01-01
  • 1970-01-01
  • 2012-12-31
  • 2018-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多