7

我正在尝试以最有效的方式运行一些核心图像过滤器。试图避免我在渲染大图像时遇到的内存警告和崩溃。我正在查看 Apple 的核心图像编程指南。关于多线程,它说:“每个线程必须创建自己的 CIFilter 对象。否则,您的应用程序可能会出现意外行为。”

这是什么意思?

我实际上是在尝试在后台线程上运行我的过滤器,所以我可以在主线程上运行 HUD(见下文)。这在 coreImage 的上下文中有意义吗?我收集到核心图像本身就使用 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 对象。否则,您的应用程序可能会出现意外行为。

4

1 回答 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. filterForThread在您传递给的块中引用dispatch_async将导致该块保留filterForThread,然后调用范围释放filterForThread,这有效地完成了对块的概念所有权的转移filterForThread(因为块是唯一留下对它的引用的东西)。filterForThread可以被认为是执行块的线程私有的。

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

于 2013-01-08T14:23:18.720 回答