ios - 在新代码之前等待 GCD 异步停止

标签 ios grand-central-dispatch

我有一个在后台运行的 GCD。我有一个按钮,当按下它时,我希望它在 GCD 完成时加载加载等待屏幕,然后执行该按钮上的其余代码。附件是样本。

我的不工作,我基本上想说,等待完成 GCD 所需的时间,同时加载等待消息,完成后继续代码。

谢谢

- (IBAction)btnTapped:(id)sender
{
    shouldCancel=NO;
    dispatch_queue_t existingQueque = dispatch_get_main_queue();//finds the current GCD, the one I created in a different method
    dispatch_group_t group =dispatch_group_create();

    dispatch_group_async(group, existingQueque, ^
    {
        dispatch_group_wait(group, DISPATCH_TIME_FOREVER);//does not work, I guess group can't be created here.
        [self performSelectorOnMainThread:@selector(showWaitViewWithMessage:) withObject:@"Loading" waitUntilDone:YES];//load this until GCD queque done

        [self performSelector:@selector(performSearch) withObject:nil afterDelay:0];
    });    
}

最佳答案

几个想法:

  1. 您建议 dispatch_get_main_queue()“找到当前 GCD,即我用不同方法创建的 GCD”。不,这只是获取主队列(如果您使用它,将阻塞您的用户界面的队列),而不是您通过 dispatch_create_queue 在别处创建的队列。 dispatch_get_main_queue() 只是获取主队列,当您进行搜索时,您的 UI 将被阻止(例如,UIActivityIndi​​catorView 不会旋转,无论如何)。

  2. 如果您已将一大堆任务分派(dispatch)到后台队列,如果您想等待所有任务完成,那就是使用 dispatch_group_tdispatch_barrier ,但鉴于您所展示的内容并不需要(您只有一个已分派(dispatch)的操作),您就不需要去那里。顺便说一句,如果您使用的是全局队列,则不建议使用障碍。

  3. 单个 GCD 后台任务的典型模式比您的问题所暗示的更简单。您 (a) 更新您的用户界面以显示“正在加载”并显示 UIActivityIndi​​catorView 或类似的东西,这样用户就有了更丰富的用户体验,向他们表明该应用正在处理某事; (b) 在后台发送搜索; (c) 完成后,将 UI 更新分派(dispatch)回主队列。因此,典型的模式是:

    - (IBAction)btnTapped:(id)sender
    {
        dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
        // or, if you've already created you own background queue just use that here, 
        // or just create one here. But don't use dispatch_get_main_queue, as that 
        // won't use a background queue.
        //
        // dispatch_queue_t backgroundQueue = dispatch_queue_create("org.yourdomain.yourapp.search", NULL);
    
        [self showWaitViewWithMessage:@"Loading"];
    
        dispatch_async(backgroundQueue, ^{
            [self performSearch];             // do this in the background
            dispatch_async(dispatch_get_main_queue(), ^{
                [self updateUiAfterSearch];   // when done, dispatch UI update back to main queue
            });
        });
    
        // if you created a queue, remember to release it
        //
        // dispatch_release(backgroundQueue); 
    }
    
  4. 顺便说一句,在您的performSelectorOnMainThread 中,我认为没有理由waitUntilDone。除非有一些令人信服的理由,否则不要等待。正如您在上面看到的,根本不需要此构造,仅供引用。

  5. 顺便说一下,重要的是要知道许多服务器对给定客户端一次可以发出的并发请求数施加限制。如果您可能会发起多个请求(例如,用户点击按钮并且服务器响应缓慢)并且这允许它们同时运行。在这种情况下,值得追求 NSOperationQueue,您可以在其中设置 maxConcurrentOperationCount。如果您使用 NSOperationQueue 方法的 block 版本(例如 addOperationWithBlock 而不是 GCD 的 dispatch_async),代码可以以相同的方式构建,但它可以让您限制后台操作的数量。

    此外,NSOperationQueue 提供了在操作之间轻松建立依赖关系的能力(例如,一个完成 NSOperation 依赖于所有其他完成)。我可以概述一下,但您发布的代码并不一定要这样,所以除非您让我知道您想看看它会是什么样子,否则我会省去您的麻烦。

关于ios - 在新代码之前等待 GCD 异步停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14062740/

相关文章:

ios - iOS 中导航 Controller 的点击手势 (MMDrawerController)

ios - Swift - 无法从 NSData 创建 JSON 对象

ios - 监视文件更改时打开太多文件

ios - Swift:与 DispatchGroup 的死锁

ios - 嵌套 dispatch_async(dispatch_get_main_queue()^{}) 的目的是什么?

ios - 为什么 NSOperationQueue 在主线程上处理大量任务时比 GCD 或 performSelectorOnMainThread 更快?

ios - 如何使用 Swift 将 ImageView 正确定位在照片顶部

objective-c - (!object) 和 (object == nil) 之间有区别吗?

ios - 将prepare for Segue 与全局变量结合使用

ios - OperationQueue.main 与 DispatchQueue.main