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

Mrw*_*lfy 7 multithreading core-image grand-central-dispatch ios

我试图以最有效的方式运行一些核心图像过滤器.试图避免内存警告和崩溃,这是我在渲染大图像时得到的.我正在看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

    });

});
Run Code Online (Sandbox Code Playgroud)

更多来自Apple Docs:

保持线程安全

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

ipm*_*mcc 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];
Run Code Online (Sandbox Code Playgroud)

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

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

  • 这里有一个类比:如果你正在写一篇论文,并且你想让5个不同的人为你审查/编辑它(同时),你就不会打印一个,把5个人围绕它,并拥有它们尝试同时进行编辑; 你会制作5份副本,并给每个评论者/编辑者一个自己的副本.同样的想法在这里 你给每个线程它自己的CIFilter副本. (2认同)