使用单个共享后台线程进行iOS数据处理? [英] Using a single shared background thread for iOS data processing?

查看:87
本文介绍了使用单个共享后台线程进行iOS数据处理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,我从网络下载了大量资源,并对每个资源进行了一些处理。我不希望这个工作发生在主线程上,但它非常轻量级和低优先级,所以所有这些都可以在同一个共享工作线程上发生。这似乎是一件好事,因为需要设置和工作。拆掉所有这些工作线程(其中没有一个会活很长时间等)。



但是,令人惊讶的是,似乎没有一个简单的方法在单个共享线程上完成所有这些工作,而不是为每个任务生成新线程。由于多年来似乎已经出现了大量实现并发的途径,这一点变得复杂。 (明确的 NSThreads NSOperationQueue ,GCD等。)



<我是否高估了产生所有这些线程所涉及的开销?我应该不会出汗,并使用更简单的每线程任务方法吗?使用GCD,并假设它比线程(重新)使用更聪明?

解决方案

使用GCD - 这是当前的官方推荐而且它比任何其他解决方案都要少。如果您明确需要传递的内容以串行方式发生(即,就像在单个线程上一样),那么您可以实现这一点但是更改可能更聪明,例如

  [self doCostlyTask]; 

收件人:

  dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0),^()
{
[self doCostlyTask];

dispatch_async(dispatch_get_main_queue(),^()
{
//大多数UIKit任务只允许来自主队列或线程,
//所以如果你想通过完成的动作更新UI,
//这是一种安全的方式来进行
[self expensiveTaskIsFinished];
});
});

这基本上告诉操作系统在低效率的情况下执行此代码,无论哪种方式最有效。您发布到任何全局队列的各种内容可能会也可能不会在彼此相同的线程上执行,也可能作为调度它们的线程执行,并且可能会或可能不会同时发生。操作系统应用它认为最优的规则。



博览会:



GCD是Apple的线程池实现,并且他们同时引入了闭包(作为块)以使其可用。所以 ^(C风格的args){code} 语法是一个块/闭包。也就是说,它的代码加上代码引用的任何变量的状态(受制于警告)。您可以在没有GCD知识或使用的情况下自行存储和调用块。



dispatch_async 是一个GCD函数向指定队列发出一个块。它在某个时间执行某个线程上的块,并应用未指定的内部规则以最佳方式执行此操作。它会根据诸如您拥有多少核心,每个核心有多忙,目前正在考虑节能(可能取决于电源),特定CPU的电力成本如何计算等因素来判断。



因此,就程序员的开发而言,块会将代码转换为可作为参数传递的代码。 GCD允许您根据操作系统可以管理的最佳调度请求执行块。块的创建和复制非常轻量级 - 比例如 NSOperation s。



GCD超越了上例中的基本异步调度(例如,你可以做一个并行for循环并等待它在一次通话中完成)但除非你有特殊需要,否则它可能并非完全相关。


I have an app where I'm downloading a number of resources from the network, and doing some processing on each one. I don't want this work happening on the main thread, but it's pretty lightweight and low-priority, so all of it can really happen on the same shared work thread. That seems like it'd be a good thing to do, because of the work required to set up & tear down all of these work threads (none of which will live very long, etc.).

Surprisingly, though, there doesn't seem to be a simple way to get all of this work happening on a single, shared thread, rather than spawning a new thread for each task. This is complicated by the large number of paths to achieving concurrency that seem to have cropped up over the years. (Explicit NSThreads, NSOperationQueue, GCD, etc.)

Am I over-estimating the overhead involved in spawning all of these threads? Should I just not sweat it, and use the easier thread-per-task approaches? Use GCD, and assume that it's smarter than I about thread (re)use?

解决方案

Use GCD — it's the current official recommendation and it's less effort than any of the other solutions. If you explicitly need the things you pass in to occur serially (ie, as if on a single thread) then you can achieve that but it's probably smarter just to change, e.g.

[self doCostlyTask];

To:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^()
{
    [self doCostlyTask];

    dispatch_async(dispatch_get_main_queue(), ^()
    {
        // most UIKit tasks are permissible only from the main queue or thread,
        // so if you want to update an UI as a result of the completed action,
        // this is a safe way to proceed
        [self costlyTaskIsFinished];
    });
});

That essentially tells the OS "do this code with low priority wherever it would be most efficient to do it". The various things you post to any of the global queues may or may not execute on the same thread as each other and as the thread that dispatched them and may or may not occur concurrently. The OS applies the rules it considers optimal.

Exposition:

GCD is Apple's implementation of thread pooling, and they introduced closures (as 'blocks') at the same time to make it usable. So the ^(C-style args){code} syntax is a block/closure. That is, it's code plus the state of any variables (subject to caveats) that the code references. You can store and call blocks yourself with no GCD knowledge or use.

dispatch_async is a GCD function issues a block to the nominated queue. It executes the block on some thread at some time, and applies unspecified internal rules to do so in an optimal fashion. It'll judge that based on factors such as how many cores you have, how busy each is, what it's currently thinking on power saving (which may depend on power source), how the power costs for that specific CPU work out, etc.

So as far as the programmer is developed, blocks make code into something you can pass around as an argument. GCD lets you request that blocks are executed according to the best scheduling the OS can manage. Blocks are very lightweight to create and copy — a lot more so than e.g. NSOperations.

GCD goes beyond the basic asynchronous dispatch in the above example (eg, you can do a parallel for loop and wait for it to finish in a single call) but unless you have specific needs it's probably not all that relevant.

这篇关于使用单个共享后台线程进行iOS数据处理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆