首页 文章

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

提问于
浏览
7

我试图以最有效的方式运行一些核心图像过滤器 . 试图避免内存警告和崩溃,这是我在渲染大图像时得到的 . 我正在看Apple的核心图像编程指南 . 关于多线程,它说: "each thread must create its own CIFilter objects. Otherwise, your app could behave unexpectedly."

这是什么意思?

我实际上试图在后台线程上运行我的过滤器,所以我可以在主线程上运行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 Docs:

维护线程安全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 可以被认为是执行块的线程的私有 .

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

相关问题