R – Using Core Graphics/ Cocoa, can you draw to a bitmap context from a background thread

bufferingcocoacore-graphicsiphonemultithreading

I'm drawing offscreen to a CGContext created using CGBitmapContextCreate, then later generating a CGImage from it with CGBitmapContextCreateImage and drawing that onto my view in drawRect (I'm also drawing some other stuff on top of that – this is an exercise in isolating different levels of variability and complexity).

This all works fine when it's all running on the main thread. However one of the motivations for splitting this out this way was so that the offscreen part could be run on a background thread (which I had thought should be ok since it's not rendering to an onscreen context).

However, when I do this the resulting image is empty! I've checked over the code, and placed judicious NSLog's to verify that everything is happening in the right order.

My next step is to boil this down to the simplest code that reproduces the issue (or find some silly thing I'm missing and fix it) – at which point I'd have some code to post here if necessary. But I first wanted to check here that I'm not going down the wrong path with this. I couldn't find anything in my travels around the googlesphere that sheds light either way – but a friend did mention that he ran into a similar issue while trying to resize images in a background thread – suggesting there may be some general limitation here.

[edit]

Thanks for the responses so far. If nothing else they have told me that at least I'm not alone in not having an answer for this – which was part of what I wanted to find out. At this point I'm going to put the extra work into getting the simplest possible example and may come back with some code or more information. In the meantime keep any ideas coming 🙂

One point to bring up: A couple of people have used the term thread safety with respect to APIs. It should be noted that there are two types of thread safety in this context:

  1. Threadability of the API itself – ie can it be used at all from more than one thread (global state and other re-entrancy issues such as C's strtok are common reasons that an API might not be thread safe too).
  2. Atomicity of individual operations – can multiple threads interact with the same objects and resources through API without application level locking?

I suspect that mention so far has been of the first type, but would appreciate if you could clarify.

[edit2 – solved!]

Ok, I got it all working. Executive summary is that the problem was with me, rather than bitmap contexts themselves.

In my background thread, just before I drew into the bitmap context, I was doing some preparation on some other objects. It turns out that, indirectly, the calls to those other objects where leading to setNeedsDisplay being called on some views!
By separating the part that did that out to the main thread it now all works perfectly.

So for anyone who hits this question wondering if they can draw to a bitmap context on a background thread, the answer is you can (with the caveats that have been presented here and in the answers).

Thanks all

Best Answer

Just a guess, but if you are trying to call setNeedsDisplay from another thread, you need to call it via performSelectorOnMainThread instead.