带有异步回调的 NSThread 与 GCD

Posted

技术标签:

【中文标题】带有异步回调的 NSThread 与 GCD【英文标题】:NSThread vs GCD with asynch callbacks 【发布时间】:2012-07-20 08:05:01 【问题描述】:

我正在使用 NSURLConnection 向我的 web 服务发出一些 http 请求,它返回一个大文本文件。显然这会阻塞主线程并增加延迟,所以我想在后台处理它。顺便说一句,我意识到有第三方框架可以处理这个特定的工作/情况,但我自己编写代码是因为我需要了解 ios 上的多线程。

我可以分离一个 NSThread 或将 NSURLConnection 代码在一个块中传递给 GCD。两种方式最初都可以正常工作(建立http连接并发送请求)。问题是如何从服务器取回数据。让我解释一下......当我的网络服务发回数据时,我的应用程序通过来自 NSURLConnectionDelegate 协议的回调得到通知。但是当这种情况发生时,我的分离线程已经退出了它的目标方法,或者该块已经被 GCD 处理并且它不在队列中(取决于我使用了哪种方法)。基本上,我的应用不会注意到回调(当然,除非我使用的是 dispatch_main_queue)。

在每种情况下解决此问题的“正确”objective-c 方法是什么?

感谢任何指导

【问题讨论】:

对我来说听起来你没有正确使用 GCD。您应该发布代码。 NSURLConnection 有一个 sendAsynchronousRequest:queue:completionHandler: 方法。你可以使用它。 【参考方案1】:

对于网络代码,我会在 NSULRConnection 上使用异步方法并处理我在后台队列中返回的数据。只有修改 UI 并且需要在主队列中的数据才会被分派(使用 GCD)到主队列。

NSOperationQueue *yourQueue = [[NSOperationQueue alloc] init];
[NSULRConnection sendAsynchronousRequest:yourRequest 
                                   queue:yourQueue 
                       completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) 

    // The code inside here gets processed once the url request completes ...
    // It happens in the background on "yourQueue".

    [self doSomeExpensiveDataProcessingWithData:data];

    dispatch_sync(dispatch_get_main_queue(), ^
        // Update UI on the main thread and wait to continue processing the data
        [self updateUI];
    );

    [self doSomeMoreDataProcessing];

    dispatch_sync(dispatch_get_main_queue(), ^
        // Update UI on the main thread and wait to continue processing the data
        [self finalUpdateOfUI];
    );
];

在网络代码示例之外,我通常喜欢将异步回调作为一种设计模式。单独测试不同的回调变得很容易,它将不同的回调(如错误处理和数据处理)划分为不同的方法,从而在这些方法中提供更集中的代码。

GCD 非常适合在另一个线程上快速执行几行代码或异步调度一些工作。

NSThread 已经很少使用了。

【讨论】:

谢谢。正是我想要的。【参考方案2】:

听起来像是一个 NSRunLoop 问题...例如阅读此内容...

http://www.sortedbits.com/nsurlconnection-in-its-own-thread/ http://www.cocoaintheshell.com/2011/04/nsurlconnection-synchronous-asynchronous/

...谷歌了解更多...

...你为什么要这样做? (在主线程上)异步使用 NSURLConnection 就足够了,然后在收到这些数据时分派您对这些数据的繁重处理。换句话说,NSURLConnection 的委托方法会在主线程上被调用,然后调度数据处理只是为了不阻塞主线程。

【讨论】:

在停下来过夜并重新考虑之后,我想出了与您建议的相同的想法。发送请求并接收它是轻量级的工作。是的,只需将繁重的处理分派给 GCD。或者,如果您想在自己的队列中完成所有操作,上述答案也是一个很好的解决方案。

以上是关于带有异步回调的 NSThread 与 GCD的主要内容,如果未能解决你的问题,请参考以下文章

GCD

微信支付异步通知的回传参数为空

带有 HTTP 回调的异步 RPC

Java之异步回调

异步 node.js:带有回调的嵌套数组

iOS:在while循环中带有块回调的异步方法