【问题标题】:Using Core Graphics/ Cocoa, can you draw to a bitmap context from a background thread?使用 Core Graphics/Cocoa,您可以从后台线程绘制位图上下文吗?
【发布时间】:2010-10-16 17:14:29
【问题描述】:

我在屏幕外绘制一个使用CGBitmapContextCreate 创建的CGContext,然后使用CGBitmapContextCreateImage 从它生成一个CGImage 并将其绘制到我在drawRect 中的视图上(我还绘制了一些其他的最重要的东西 - 这是一个隔离不同级别的可变性和复杂性的练习)。

当它全部在主线程上运行时,这一切都很好。然而,以这种方式拆分它的动机之一是让屏幕外部分可以在后台线程上运行(我认为这应该没问题,因为它没有渲染到屏幕上下文)。

但是,当我这样做时,结果图像是空的!我检查了代码,并放置了明智的 NSLog 以验证一切都以正确的顺序发生。

我的下一步是将其归结为重现问题的最简单的代码(或找到我遗漏的一些愚蠢的东西并修复它)——如果有必要,我会在此处发布一些代码。但我首先想在这里检查一下我不会走错路。我在 googlesphere 周围的旅行中找不到任何可以揭示任何一种方式的东西 - 但一位朋友确实提到他在尝试在后台线程中调整图像大小时遇到​​了类似的问题 - 这表明这里可能存在一些一般限制。

[编辑]

感谢您迄今为止的回复。如果没有别的,他们告诉我,至少我不是唯一一个对此没有答案的人——这是我想知道的一部分。在这一点上,我将投入额外的工作来获得最简单的示例,并且可能会返回一些代码或更多信息。同时保持任何想法:-)

提出一点:有几个人在 API 方面使用了线程安全这个术语。需要注意的是,在这种情况下线程安全有两种类型:

  1. API 本身的线程性 - 即它是否可以在多个线程中使用(全局状态和其他可重入问题,例如 C 的 strtok 是 API 可能不是线程安全的常见原因)。李>
  2. 单个操作的原子性 - 多个线程能否通过 API 与相同的对象和资源进行交互,而无需应用程序级锁定?

我怀疑到目前为止提到的是第一种类型,但如果您能澄清一下,将不胜感激。

[edit2 - 已解决!]

好的,我搞定了。执行摘要是问题出在我身上,而不是位图上下文本身。

在我的后台线程中,就在我绘制位图上下文之前,我正在对其他一些对象进行一些准备工作。事实证明,间接地,对导致 setNeedsDisplay 在某些视图上调用的其他对象的调用! 通过将执行此操作的部分分离到主线程,它现在一切正常。

因此,对于遇到此问题的任何人想知道他们是否可以在后台线程上绘制位图上下文,答案是您可以(此处和答案中提供了警告)。

谢谢大家

【问题讨论】:

  • 您对问题和解决方案的详细描述帮助我弄清楚我自己的代码出了什么问题。非常感谢!

标签: iphone cocoa multithreading core-graphics buffering


【解决方案1】:

只是猜测,但如果您尝试从另一个线程调用 setNeedsDisplay,则需要改为通过 performSelectorOnMainThread 调用它。

【讨论】:

  • 谢谢。但我是从主线程调用它。我在另一个线程上做的唯一一件事就是绘制位图上下文
  • 我将您的文章标记为已接受,因为事实证明它最接近原因 - 即使它没有直接引导我 :-)
【解决方案2】:

如果您在一个且只有一个线程中使用 CGContextRef,那么您所做的应该可以工作。我之前用 8 个内核处理图像的 8 个不同部分,然后将不同的结果 CGImageRef 合成在一起并在屏幕上绘制它们。

【讨论】:

  • 谢谢。我没有在我的问题中提到它,但确实添加了 iPhone 标签,这在这里可能重要也可能不重要(正如 Roger Nolan 在他的回答中提到的那样)
【解决方案3】:

Apple 没有提及 iPhone 上的线程安全,但 Cocoa(相对于 UIKit)是 generally thread safe for drawing。由于他们共享大量绘图代码,我认为在 iPhone 上绘图是线程安全的。

也就是说,您的经验表明存在问题。会不会是你在渲染之前使用了你的图像?

【讨论】:

  • 没有。在我的线程方法结束时,我设置了对主线程上另一个方法的调用,该方法又调用 setNeedsDisplay。只有在这一点上,图像才会从位图上下文中生成并用于绘制到视图
【解决方案4】:

并非所有 API 都是线程安全的。有些需要锁定或要求它们在主线程上运行。您可能需要搜索文档。我相信有一个页面总结了 SDK 的哪些部分是线程安全的,哪些不是。

【讨论】:

  • 谢谢凯洛亚。我很欣赏你的回应,但这几乎是我开始的地方。我希望有更多的细节,因为我的“搜索文档”还没有找到任何确定的东西。
【解决方案5】:

如果有人正在/正在寻找如何做到这一点,我已经写了一个 blog post 来描述如何做到这一点,并将整个事情包装在一个 NSOperation 子类中。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多