我试图以最有效的方式运行一些核心图像过滤器。试图避免内存警告和崩溃,这是我在渲染大图像时得到的。我正在看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 Docs的更多内容:
维护线程安全
CIContext和CIImage对象是不可变的, 这意味着每个都可以在线程之间安全地共享。多线程 可以使用相同的GPU或CPU CIContext对象来渲染CIImage 对象。但是,CIFilter对象不是这种情况 可变的。无法在线程之间安全地共享CIFilter对象。如果 您的应用程序是多线程的,每个线程必须创建自己的CIFilter 对象。否则,您的应用可能会出现意外行为。
答案 0 :(得分: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];
这里发生的是filterForThread
是myFilter
的副本。在您传递给filterForThread
的块中引用dispatch_async
将导致该块保留filterForThread
,然后调用范围将释放filterForThread
,这有效地完成了{的概念所有权的转移{1}}到块(因为块是唯一留下引用它的东西)。 filterForThread
可以被认为是执行块的线程的私有。
这应该足以满足此处的线程安全要求。