It seems to be a recurring topic here on my blog, threading. I was asked to look at a problem for a client yesterday and discovered a very subtle threading issuing (I actually didn’t create it, one of the other people on the project created the problem when he added some code). Basically in order to show progress while the app is doing stuff, some code is executed on a separate thread. However, the main thread basically spins in a loop using something like:
while (threadRunning) { NSDate *newDate = [[NSDate alloc] initWithTimeIntervalSinceNow:0.05]; [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:newDate]; [newDate release]; }
The application uses CoreData for managing data and the second thread accesses the CoreData store. You would think that the above code blocks the main thread from doing anything while the second thread is running, but like my issue with NSTask, the main thread is actually doing something. In this case, the UI is bound using Cocoa bindings to the managed object context and the secondary thread was also using the same managed object context. As explained in Apple’s docs on Core Data multi-threading, you could get a deadlock when 2 threads are accessing the same managed object context at the same time. Bindings hid the fact that they were talking to the managed object context. I should have realized this, but I didn’t.
Will I ever learn about how to get threading right?