Ken Aspeslagh is somewhat incorrect about drawing from secondary threads (he is correct it is generally a bad idea). From what I can see of your code you don't have a good use case for drawing on a secondary thread. Can you explain why you want to do this?
you yourself have already discovered setCanDrawConcurrently:
which explicitly talks of invoking drawRect:
from a background thread. Note that the views window must have allowsConcurrentViewDrawing
set to YES for this to work (it is the default).
Apples own Cocoa Drawing Guide has a section on drawing from secondary threads. I have highlighted some portions I think are relevant to you.
The Application Kit maintains a unique graphics context for each window and thread combination. Because each thread has its own graphics context object for a given window, it is possible to use secondary threads to draw to that window. There are some caveats, however.
During the normal update cycle for windows, all drawing requests are sent to your application’s main thread for processing. The normal update cycle happens when a user event triggers a change in your user interface. In this situation, you would call the setNeedsDisplay: or setNeedsDisplayInRect: method (or the display family of methods) from your application’s main thread to invalidate the portions of your view that require redrawing. You should not call these methods from any secondary threads.
If you want to update a window or view from a secondary thread, you must manually lock focus on the window or view and initiate drawing yourself. Locking focus configures the drawing environment for that window's graphics context. Once locked, you can configure the drawing environment, issue your drawing commands as usual, and then flush the contents of the graphics context to the window buffer.
In order to draw regularly on a secondary thread, you must notify the thread yourself. The simplest way to send regular notifications is using an NSTimer or NSAnimation object. For more information on how to animate content, see “Advanced Drawing Techniques.”
The Cocoa Threading Programming Guide also says this:
If you want to use a thread to draw to a view, bracket all drawing code between the lockFocusIfCanDraw and unlockFocus methods of NSView
Just an aside, GCD block invocation is probably a much nicer method for performing small sets of operations in the background than NSThread
.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
// you can put each of these calls in their own queue if you want
[self DrawText];
[self DrawRectangle];
[self DrawGradient];
});
However, that likely has nothing to do with your problem; I mention it only because I think it will serve you better to use GCD queues.