8

Objective-C 块是否总是在单独的线程中执行?

具体来说,我询问的是 NSURLConnection 类的 sendAsynchronousRequest:queue:completionHandler 方法。这是场景:

主线程(第一个线程)调用 sendAsynchronousRequest 方法 sendAsynchronousRequest 在第二个线程上执行,方法完成时由 NSOperationQueue 管理并调用commpletionHandler,它在哪个线程上执行?第二个线程?还有第三个线程?还是第一个线程?

谢谢!

4

4 回答 4

7

它在您指定为queue参数的任何操作队列上执行它:

加载 URL 请求的数据并在请求完成或失败时在操作队列上执行处理程序块。

queue参数记录为:

当请求完成或失败时,处理程序块被分派到的操作队列。

因此,这实际上取决于使用NSOperationQueue了多少线程。我希望池行为 - 因此虽然可以有多个线程,但我不希望每个处理程序有不同的线程,必然。

于 2012-10-02T06:06:49.417 回答
7

块只是一个闭包,就像你在 python 或函数式语言中拥有它们一样。它们不会“在线程上运行”,而是在调用它们的地方运行。

int main(void)
{
    void (^f)(void) { printf("hello world!\n"); }
    f();
    return 0;
}

做你认为它做的事,没有调度队列,没有线程,什么都没有。

但是,一旦您拥有具有所有良好捕获语义的块,就很容易让 API 来安排它们在任何地方的执行。但基本上,一个块与一个函数指针和一个包含所有捕获变量的临时结构相同,作为参数传递给回调(甚至它在编译器中的实现方式也是如此)。

于 2012-10-25T21:53:19.730 回答
4

块在被告知的任何地方执行。将代码包装在块中不会影响将在其上运行的线程或队列。在您的特定情况下,如文档所述,完成块在queue参数中传入的队列上执行。

我不确定,对于您的目的,如果您确实需要区分队列和线程,关键原则是URL请求与调用代码异步执行,并在传入的队列上执行完成块作为方法参数。

于 2012-10-02T06:07:59.110 回答
4

正如其他人所说,它将在您指定的任何队列上运行。如果这是一个后台队列,并且你想在主线程上执行一些代码,你可以包含一个访问主队列的 GCD 块。您的完成块看起来像这样:

^(NSURLResponse *response, NSData *data, NSError*error){

   // do whatever in the background

   dispatch_async(dispatch_get_main_queue(), ^{
   // this block will run on the main thread
   });
}
于 2012-10-02T06:10:31.757 回答