【问题标题】:Schedule a low-priority task on the main thread在主线程上调度低优先级任务
【发布时间】:2012-02-01 21:39:08
【问题描述】:

我有一个相当慢(100-200 毫秒)的 drawRect 方法。为了节省时间,我需要缓存结果。我正在做这样的实际缓存:

// some code to check if caching would be desirable goes here.  If it is desirable, then
UIGraphicsBeginImageContext(viewSize);
CGContextRef c = UIGraphicsGetCurrentContext();
[view.layer renderInContext: c];
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
[self.cachedImageArray addObject:image];
UIGraphicsEndImageContext();

缓存本身最多可能需要 40 毫秒。这仍然很值得。但是缓存必须等到所有内容都渲染完毕,否则会出错。此外,缓存是一个低优先级的任务。一旦所有的东西都显示出来了,其他的事情可能还在继续,如果是这样,缓存可以等待。但由于它使用 UIKit,它必须在主线程上。

与其随意拖延,有没有一种防弹的方法可以像这样等待?

【问题讨论】:

  • 为什么缓存任务必须在主线程上?难道你不能在主线程上发送(或显示)结果(通过performSelectorOnMainThread 或GCD 的魔法dispatch_async(dispatch_get_main_queue(), ^{ }); 并在drawRect 末尾附近的单独线程上分离缓存吗?
  • 从 iOS 4 开始,绘制到图形上下文是线程安全的,不必在主线程上执行。您可以使用 dispatch_async() 将整个事情踢到后台线程。

标签: iphone ios caching uiimage image-caching


【解决方案1】:

缓存本身不必在主线程上完成。您可以获得图像上下文或位图数据的副本/引用,并仅在渲染完成后使用 NSThread 启动它。示例:

- (void) drawRect:(CGRect)rect {
    do_rendering_here();
    // when rendering completed:
    NSThread *t = [[NSThread alloc] initWithTarget:self selector:@selector(doCaching:) object:c];
    [t start];
    [t release];
}

- (void) doCaching:(CGContextRef)ctx {
    // do whatever kind of caching is needed
}

【讨论】:

  • 仍然允许使用 `NSThread,但 Apple 建议不要在大多数任务中使用它。他们更希望您使用 Grand Central Dispatch 并使用@MichaelDautermann 对问题的评论中的解决方案。查看 Apple 的并发指南:developer.apple.com/library/ios/#documentation/General/…
  • 抱歉,我不熟悉这些新 API,因为我没有任何支持 iOS5 的设备,而且我有一个从 3.1.3 标头构建的旧工具链...
  • @H2CO3 - GCD 是在 iOS 4.0 中出现的,所以现在已经支持了一段时间。此外,无需对 NSThread 实例进行复杂的分配即可在后台线程上执行某些操作。只需使用 NSObject 的-performSelectorInBackground:withObject:
  • 谢谢,我可能表达错了;我知道这些,我只是不能使用它们,因为我不习惯它们。
猜你喜欢
  • 2012-08-30
  • 2014-11-26
  • 1970-01-01
  • 2011-04-19
  • 1970-01-01
  • 1970-01-01
  • 2014-10-27
  • 1970-01-01
相关资源
最近更新 更多