目标C中最好的multithreading方法?

我正在开发一个iPad应用程序,我目前正在努力寻找最佳的multithreading方法。 让我用一个简单的例子来说明这一点:
我有一个包含2个子视图的视图,一个目录select器和一个带有所选目录中所有图像缩略图的图库。 由于“下载”和生成这些缩略图可能需要相当长的一段时间我需要multithreading,因此视图的交互和更新不会被阻止。

这是我已经尝试过的:
[self performSelectorInBackground:@selector(displayThumbnails 🙂 withObject:currentFolder];
这工作正常,因为用户交互没有被阻止,但是当用户在第一个文件夹仍在加载的同时点击另一个文件夹时,它失败了。 两个线程正试图访问相同的视图和variables,导致彼此正确执行。 当用户点击另一个文件夹时,当前正在加载的文件夹的显示displayThumbnails应该被中止。 我没有find任何办法做到这一点..

NSThreads
我试过这个,但和第一种方法几乎一样的问题,我没有find一个(简单的)方法来取消正在进行的方法。 (是的,我知道[aThread cancel]但没有find一种方法来“恢复”线程)。 也许我应该NSThread并实现我自己的isRunning等方法? 但是没有更好的办法,或者我忽略了第三种(甚至是第四种和第五种)选项吗?

我认为这是一个相当简单的例子,我认为没有NSThread也许有更好的解决scheme。 那么,你会怎么做? 你的意见请!

NSOperationQueue应该适合这个任务。

另一个select是简单的GCD ,但是,如果你从来没有使用它,NSOperationQueue可能是更好的select,因为它几乎自动地引导你“以正确的方式”实现的东西,有明显的取消方式等。

你想使用Concurrent NSOperations在后台下载和处理图像。 这些将由NSOperationsQueuepipe理。 实质上,这些操作将被configuration为每个操作获取一个图像,处理它,将其保存在文件系统中,然后消息回到图像可用的主线程中的主应用程序。

在github上有几个项目,你可以看看如何做到这一点 – 只需使用“并发”或“NSOperation”searchgithub。

iOS有一个非常好的工具来完成后台工作。 大中央调度(GCD)和块,但这些不让你有一个对象使用委托callback – 因此NSOperation。

所以你需要阅读块,GCD,然后看看一些开源的Concurrent NSOperations代码。 使用Concurrent NSOperations并不像使用块那么简单。

如果我有这个问题,我可能会采取这样的方法:

  • 一个单独的线程,将加载图像,并导致主线程显示结果(我不是一个线程搞乱GUI对象的大风扇)

  • 当一个新的目录被请求…嗯,这取决于你想如何pipe理的事情。 基本上,主线程可以使用一个标准的队列结构(条件variables和数组)来通过传递path名来告诉线程“这个目录是需要的” 即使在加载图像时,线程也会检查队列(比如在每个图像之后),并且每当出现图像时切换到新的目录

  • 您可以创build一个保存所有状态的目录读取器对象,并将此path索引存储到字典中。 当请求一个新的目录时,首先检查该字典,如果这个目录没有,则只创build一个新的对象。 这样一来,部分加载的目录就会一直存在,直到它们再次被需要,并且可以继续加载而不必从头开始。

线程的伪代码:

 while (forever) new element = nil if we have an active directory loader tell directory loader to load one image if false then make directory loader inactive lock queue condition if queue has elements new element = retrieve LAST element (we aren't interested in the others) empty queue unlock with status "empty" else unlock queue else lock queue on condition "has elements" new element = retrieve last element empty queue unlock with status "empty" if new element != nil if directory loader for new path does not exist setup new directory loader for new path store in dictionary make it the "active" one else make the current one the "active" 

至于目录加载器,它可能看起来像这样:

 read one image: if there are still images to read: read, process and store one return true else performSelectorOnMainThread with an "update GUI" method and the image list as parameter return false; 

这只是一个快速的草图; 线程中有一些代码重复,我写的方式只会在所有图像被读取后更新GUI,而不是在我们读取它们时出现。 您必须复制当前的图像列表,或者添加同步,如果你想这样做。