iOS:核心图像和多线程应用程序

7
我正在尝试以最高效的方式运行一些核心图像滤镜。当渲染大型图像时,我会遇到内存警告和崩溃问题。我在查看苹果的《Core Image编程指南》。关于多线程,它说:“每个线程必须创建自己的CIFilter对象。否则,你的应用程序可能会出现意外行为。”
这是什么意思?
事实上,我正在尝试在后台线程上运行我的滤镜,以便我可以在主线程上运行一个HUD(请参见下文)。在CoreImage的背景下,这是否有意义?我了解到Core Image本质上使用GCD。
//start HUD code here, on main thread

// Get a concurrent queue form the system
dispatch_queue_t concurrentQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{

    //Effect image using Core Image filter chain on a background thread

    dispatch_async(dispatch_get_main_queue(), ^{

        //dismiss HUD and add fitered image to imageView in main thread

    });

});

更多 Apple 文档内容:

保证线程安全

CIContext 和 CIImage 对象是不可变的,这意味着每个对象都可以在线程之间安全地共享。多个线程可以使用相同的 GPU 或 CPU CIContext 对象来渲染 CIImage 对象。然而,对于 CIFilter 对象情况并非如此,它们是可变的。CIFilter 对象不能在线程之间安全地共享。如果您的应用程序是多线程的,每个线程必须创建自己的 CIFilter 对象。否则,您的应用程序可能会表现出意料之外的行为。

1个回答

12

我不确定该如何用不同的方式表达它:每个后台线程都需要创建自己的CIFilter对象版本以在您的滤镜链中使用。实现这一点的一种方法是为每个后台操作复制您的滤镜链,使用dispatch_async(...)。在您发布的代码中,可能看起来像这样:

//start HUD code here, on main thread
// Assuming you already have a CIFilter* variable, created on the main thread, called `myFilter`
CIFilter* filterForThread = [myFilter copy];
// Get a concurrent queue form the system
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
    CIFilter filter = filterForThread;

    // Effect image using Core Image filter chain on a background thread

    dispatch_async(dispatch_get_main_queue(), ^{

        //dismiss HUD and add fitered image to imageView in main thread

    });

});
[filterForThread release];

这里发生的是,filterForThreadmyFilter 的一个副本。在传递给 dispatch_async 的块中引用 filterForThread 会导致该块保留 filterForThread,然后调用范围释放 filterForThread,这有效地完成了将 filterForThread 的概念所有权转移给块的过程(因为该块是唯一仍然引用它的东西)。可以认为 filterForThread 是在执行块的线程中私有的。

这应该足以满足此处的线程安全要求。


1
谢谢。我会读你的答案几十遍,也许它会慢慢地被理解 :). - OWolf
2
这里有一个类比:如果你正在写一篇论文,并且希望有5个不同的人同时为你审查/编辑它,你不会只打印一份,让5个人围在一起尝试同时进行编辑;你会制作5份副本,并分别给每个审阅者/编辑者。这里的想法是相同的。你为每个线程提供了它自己的CIFilter副本。 - ipmcc
只是想说谢谢,这节省了我大量的时间和重新制定其他解决方案。它非常有效地处理过滤器,同时保持用户界面的流畅运行。 - AndyDunn

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接