何时使用dispatch_get_main_queue

时间:2014-09-11 19:26:52

标签: ios asynchronous grand-central-dispatch mknetworkkit

我在iOS中学到了一个全局规则 - >永远不要阻止主线程。 但是,有几次我遇到违反此规则的开源代码片段。

以下是两个例子:

以下功能取自 https://github.com/piwik/piwik-sdk-ios/blob/master/PiwikTracker/PiwikTracker.m

- (void)startDispatchTimer {

  // Run on main thread run loop
  __weak typeof(self)weakSelf = self;
  dispatch_async(dispatch_get_main_queue(), ^{

    [weakSelf stopDispatchTimer];

    // If dispatch interval is  0) {

      // Run on timer
      weakSelf.dispatchTimer = [NSTimer scheduledTimerWithTimeInterval:weakSelf.dispatchInterval
                                                                target:weakSelf
                                                              selector:@selector(dispatch:)
                                                              userInfo:nil
                                                               repeats:NO];

      NSLog(@"Dispatch timer started with interval %f", weakSelf.dispatchInterval);

    }

  });

}

在上面的代码中,我一直试图理解为什么定时器对象需要主线程。像这样的东西不是UI相关的,仍然在主线程上完成。

另一个例子是着名的网络库MKNetworkKit。 以下代码在NSOperation的start方法中。 https://github.com/MugunthKumar/MKNetworkKit/blob/master/MKNetworkKit/MKNetworkOperation.m


dispatch_async(dispatch_get_main_queue(), ^{
      self.connection = [[NSURLConnection alloc] initWithRequest:self.request
                                                        delegate:self
                                                startImmediately:NO];

      [self.connection scheduleInRunLoop:[NSRunLoop currentRunLoop]
                                 forMode:NSRunLoopCommonModes];

      [self.connection start];
    });

所以我的问题是为什么人们使用主线程来做没有UI相关的操作,它给了什么好处。如果你没有抓住它,它可能不会冻结你的应用程序,但为什么要抓住机会。

1 个答案:

答案 0 :(得分:2)

两个示例都直接或间接使用NSRunLoop方法。在这些情况下,您应该从执行目标NSRunLoop的线程调用方法。因此,您需要dispatch_get_main_queue()。

查看有关NSRunLoop https://developer.apple.com/library/ios/documentation/cocoa/reference/foundation/classes/nsrunloop_class/reference/reference.html

的Apple文档
  

警告:NSRunLoop类通常不被认为是线程安全的,并且只应在当前线程的上下文中调用其方法。您永远不应该尝试调用在不同线程中运行的NSRunLoop对象的方法,因为这样做可能会导致意外结果。

顺便说一句,NSRunLoop似乎在Core Foundation中使用CFRunLoop,Core Foundation是在Apple的开源许可下发布的。

http://opensource.apple.com/source/CF/CF-855.17/CFRunLoop.c

似乎CFRunLoop是线程安全的(我们可以看到很多__CFRunLoopLock和__CFRunLoopUnlock组合)。但无论如何你最好还是遵守文件:)