iOS 长时间运行使用 GCD 或 NSThread?

2024-01-10

我是 iOS 开发新手(我最熟悉 Java),我想知道启动长时间运行的线程的最佳方法是什么?只要应用程序位于前台,该线程就会启动,并在进入后台时停止。当它位于前台时,它将每隔 X 秒轮询一次外部设备以查看其是否已连接。

NSThread 与 Java 线程类非常相似,这使得我很容易理解。我知道我可以initWithTarget:selector:object:那个班级和电话start:它将使用选择器中提供的方法启动线程。在那里我只有一个while(true)循环继续运行,直到我打破它。这是我想要做的一个基本示例:

- (void)startup {
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(devicePoller) object:nil];
    [thread start];
}

- (void)devicePoller {
    while (self.started) {
        if (![self.device isConnected]) {
            //notify the user the device isn't connected
        }

        [NSThread sleepForTimeInterval:2];
    }
}

然而,我看到人们推荐使用 GCD,因为它具有更好的性能。我明白如何使用dispatch_async()用于异步执行代码,但所有示例似乎都是针对单个长时间运行的操作,而不是在应用程序运行的整个过程中运行的操作。有没有办法用 GCD 来做到这一点(我应该)或者其他什么?


如果您需要轮询并且想在后台线程上执行此操作,我可能建议使用调度计时器:

@property (nonatomic, strong) dispatch_source_t timer;

然后您可以将此计时器配置为每两秒触发一次:

dispatch_queue_t queue = dispatch_queue_create("com.domain.app.devicepoller", 0);
self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
dispatch_source_set_timer(self.timer, dispatch_walltime(NULL, 0), 2.0 * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(self.timer, ^{
    [self pollDevice];    // this method should just poll the device and then return; no loop needed in this method
});
dispatch_resume(self.timer);

参见讨论调度来源 https://developer.apple.com/library/mac/documentation/General/Conceptual/ConcurrencyProgrammingGuide/GCDWorkQueues/GCDWorkQueues.html#//apple_ref/doc/uid/TP40008091-CH103-SW1 in the 并发编程指南。另请参阅Grand Central Dispatch (GCD) 参考 https://developer.apple.com/library/mac/documentation/performance/reference/gcd_libdispatch_ref/Reference/reference.html.

但是大多数设备都支持某种形式的事件驱动通知,这样就不需要进行任何像这样的轮询,但是如果您必须轮询,并且您想在主线程之外进行轮询,那么这是一种方法。


当您希望计时器在后台队列上运行时,调度计时器非常有用。如果您的供应商的 API 的响应速度足以在主队列中无缝运行,则使用NSTimer方法。它使您不必做很多额外的工作来使您的代码线程安全(例如,正确的同步 https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW1当您更新模型对象等时)。我从你最初问题的基于线程的方法中假设你有某种原因不使用计时器,并且由于某种原因你必须将其移动到另一个线程,在这种情况下我认为调度计时器可能是处理它的更好方法比做NSThread永久编程while环形。但如果您 (a) 必须进行民意调查; (b) 没有迫切需要编写多线程代码,那么如果您使用过,您的生活可能会更简单NSTimer基于的方法。

就我个人而言,我会确保我用尽了核心蓝牙 https://developer.apple.com/library/ios/documentation/NetworkingInternetWeb/Conceptual/CoreBluetooth_concepts/PerformingCommonCentralRoleTasks/PerformingCommonCentralRoleTasks.html#//apple_ref/doc/uid/TP40013257-CH3-SW1在我追求计时器之前的方法。物理设备的应用程序级轮询应被视为最后手段。也许您可以联系 API 的供应商,看看他们是否有除了轮询之外的建议(因为如果他们已经这样做了一段时间,他们可能有更优雅的解决方案可以建议)。

关于接收网络服务更新,轮询的效率又非常低(并且根据轮询的频率,它可能会对电池寿命产生不利影响,消耗蜂窝数据计划等)。推送通知 https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Introduction.html如果服务器数据不经常更改,但您希望您的应用程序能够主动收到更改通知,那么这可能是一种可行的方法。或者,如果服务器确实在不断变化,那么也许某种基于套接字的方法可能有意义。但是每两秒轮询一次网络资源(如果这就是您的建议)很少是正确的方法。

就像物理设备的轮询是最后手段的架构一样,对于网络通信来说更是如此。您确实希望提出一种能够平衡设备考虑因素和业务需求的架构。如果您得出结论必须采用基于轮询的方法,也许您可​​能会考虑根据用户是否使用 WiFi 或蜂窝网络而采用不同的轮询频率。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

iOS 长时间运行使用 GCD 或 NSThread? 的相关文章

随机推荐

  • 在给定元素下通过 XPath 搜索

    我知道在 PHP 中对 DOM 执行 XPath 查询的唯一方法是DOMXPath http php net manual fr class domxpath php 它仅适用于DOMDocument public construct DO
  • 如何配置 uwsgi 将日志记录编码为 json(应用程序输出除外)

    我正在 Python Flask Web 应用程序周围运行 uwsgi 并使用这些选项 以及其他选项 在 stdout 上获取 JSON 编码的日志记录 fmt timestamp strftime FT TZ level DEBUG na
  • 关于虚函数的问题

    我有两节课 class x public virtual void hello std cout lt lt x lt lt std endl class y public x public void hello std cout lt l
  • Spring MVC 表单验证:如何使字段可选?

    我有一个表单 Spring 3 MVC 项目 我使用 DTO 数据传输对象 进行数据验证 数据被发送到控制器 我正在检查它的有效性BindingResult hasErrors 方法和适当的注释 由于我在数字字段方面遇到问题 因此我将在这里
  • 摆动组件之间的新线

    我曾多次尝试多次搜索如何格式化 java swing 元素 但我似乎找不到任何东西 我尝试学习网格袋布局 但它太复杂了 有人可以告诉我如何使用 Swing 来设置 Swing 组件的空间吗 谢谢 EDIT Code import javax
  • 当将 Google Sheets API 写入工作表放在具有从脚本读取的页面上时,写入工作表不起作用

    我在写入 Google 表格时遇到问题 我不明白为什么 我刚开始使用此 API 并且一直在使用 JavaScript 客户端库的 Google API 客户端库指南 我正在尝试构建一个 登录 网页来跟踪某人参加活动的时间 当我的页面加载时
  • FromBase64String/UTF 编码

    我的问题是基于我从 API 调用中返回的一串数据 我将原始数据传递到 FromBase64String 中 然后将字节数组编码回字符串 我期待一个有效的 pdfsharp 返回 并将其保存到文件中 下面的解码字符串值都不包含正确的数据 我知
  • 从 glob 表达式创建正则表达式

    我编写了用正则表达式解析文本的程序 应从用户处获取正则表达式 我打算使用 glob 语法进行用户输入 并在内部将 glob 字符串转换为正则表达式 例如 foo bar 应转换为 foo w bar w 不知何故 我需要从字符串中转义所有有
  • R:如何将嵌套列表“取消嵌套”到 data.frame 中?

    I have l1 list SeriousDlqin2yrs list prediction 0 prediction probs list 0 0 5 1 0 5 l2 list SeriousDlqin2yrs list predic
  • CSS 中的 id 和 class 有什么区别,什么时候应该使用它们? [复制]

    这个问题在这里已经有答案了 main background 000 border 1px solid AAAAAA padding 10px color fff width 100px div Welcome div 这里我给出了一个id
  • Java 8 中 MetaSpace 有什么用?

    我知道他们在 Java 8 中用 MetaSpace 取代了 PermGen 但我有几个问题 MetaSpace默认是GC收集的吗 甚至 PermGen 也是通过添加参数进行 GC 收集的 例如 XX CMSClassUnloadingEn
  • CSS 不透明度动画 Safari 错误?

    我有一个简单的动画 本例中仅适用于 Safari h1 webkit animation moveDown 1s ease in out webkit keyframes moveDown 0 webkit transform transl
  • 单击 Activity 上的其他位置时如何使 SearchView 失去焦点并折叠

    在我的应用程序中 我正在制作一个搜索界面 http developer android com training search setup html其中SearchView当它失去焦点和获得焦点时分别会折叠和扩展 然而 失去焦点的情况只发生
  • 无法使用 ChromeDriver 下载文件

    我正在使用 chromedriver 和 selenium 从应用程序下载文件 但是 当单击应用程序中的下载按钮时 它给出错误 Failed Download error Chrome 驱动程序版本 2 21 硒版本 2 53 0 用于初始
  • 如何在html中设置输入类型=文件的样式? [复制]

    这个问题在这里已经有答案了 我做了一些研究 发现很难设计输入类型 文件的样式 然而 我意识到当您想要将视频上传到该网站时 YouTube 会显示一个漂亮的按钮 可能需要登录 http www youtube com upload http
  • 如何使用 docx4j 读取 Word 文档并获取其中所有样式的部分

    我正在使用 docx4j 来处理 Word 文档格式 我有一个word文档 它分为多个表格 我想阅读所有表格 如果我找到一些关键字 那么我想将这些内容转移到另一个具有所有格式的 Word 文档中 我的word文档如下 就像上面一样 我想获取
  • NSPredicate 用于检测子查询中的非空关系

    给定核心数据实体设置如下 Entity A Bs gt B 多对多 Cs gt C 多对多 孩子 gt 孩子 多对多 Entity B 孩子 gt 孩子 多对多 Entity C 孩子 gt 孩子 多对多 Child date 我想要查询实
  • 如何扩展JavaDoc 5.0标准doclet?

    我想扩展Javadoc5 0提供的标准doclet来修改其HTML输出 例如 当关键字 implemented 或 Interfaces 出现在生成的 JavaDoc HTML 中时 我想将其替换为另一个单词 所有其他元素不应更改 我怎样才
  • 使用 Python 2.7 从 Excel 导入 MySQL 表

    我正在尝试将此 Excel 工作表中的数据插入到 MySQL 表中 https www dropbox com s w7m282386t08xk3 GA xlsx dl 0 https www dropbox com s w7m282386
  • iOS 长时间运行使用 GCD 或 NSThread?

    我是 iOS 开发新手 我最熟悉 Java 我想知道启动长时间运行的线程的最佳方法是什么 只要应用程序位于前台 该线程就会启动 并在进入后台时停止 当它位于前台时 它将每隔 X 秒轮询一次外部设备以查看其是否已连接 NSThread 与 J