ios - 何时使用dispatch_get_main_queue

标签 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 相关的操作以及它有什么好处。如果您不坚持使用它,它可能不会卡住您的应用程序,但为什么要冒险呢?

最佳答案

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

看一下苹果关于NSRunLoop的文档 https://developer.apple.com/library/ios/documentation/cocoa/reference/foundation/classes/nsrunloop_class/reference/reference.html

Warning: The NSRunLoop class is generally not considered to be thread-safe and its methods should only be called within the context of the current thread. You should never try to call the methods of an NSRunLoop object running in a different thread, as doing so might cause unexpected results.

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

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

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

关于ios - 何时使用dispatch_get_main_queue,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25795565/

相关文章:

c++ - 专用队列上的 GCD block 停止执行大型 SQLite3 数据库

ios - xcode 跳转条符号表示

asynchronous - 可以使用命令的 gvim 远程选项卡吗?

java - 在执行线程上运行 Spring 方面建议

javascript - Nodejs 并行异步调用,但有优先权

ios - 带有 Realm 支持的数据库和在线同步的 UITableView

iphone - 设置 UITableView 的样式

ios - iOS 是否存储用户的性别?

ios - OpenCv for iphone 构建错误

macos - 如何在释放时清空并完全释放 Grand Central Dispatch 队列?