This is the error I am getting:
MonoMac.AppKit.AppKitThreadAccessException: AppKit Consistency error: you are calling a method that can only be invoked from the UI thread.
I want to lay out my program as shown in the apple documentation figure 14-1.
The following stack-overflow question seems to suggest this can be achieved in cocoa
The documentation seems to state that multiple gl context are perfectly plausible, so I'm guessing that at least some of these must exist outside of the main UI thread.
I am guessing that this could well be the problem. However I want to make sure that a nsglcontext in a separate thread is not implicitly dangerous and that one just has to follow the usual precautions one does when working with multi-threaded opengl programs.
Any help would save my table from being head-butted any more and thus would be greatly appreciated.
As suggested in the blog post link in the question you can use the following to turn of cross thread ui checks.
//
// Disable UIKit thread checks for a couple of methods
//
var previous = UIApplication.CheckForIllegalCrossThreadCalls;
UIApplication.CheckForIllegalCrossThreadCall = false;
// Perform some UIKit calls here
foo.Bar = 1;
// Restore
UIApplication.CheckForIllegalCrossThreadCalls = previous;
Do note though if you are doing the wrong thing this would also hide the problem, so use this sparingly.
Related
A common pattern in Objective C is to run a bit of code in a background thread, then go back to the main thread to make UI adjustments. If the code starts in the main thread, I'd attack this with a pattern like so:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self someBackgroundTask];
dispatch_async(dispatch_get_main_queue(), ^{
[self someUITask];
});
});
However, this seems like a really clunky way to do it, not in the least because it creates two levels of nesting that feeling unnecessary. Is there a better way to do this? Note that the UI code is considered in this instance to be relying on the background task completing, so it can't just be dropped after the first dispatch.
Just move all the threading stuff into someBackgroundTask:
[self someBackgroundTaskWithCompletion:^{
[self someUITask];
}];
Then do your dispatch_async() stuff inside the background task method.
Conceptually, you need to run code on two different threads. All UI operations must run on the main thread, and your blocking operation needs to run on a background thread. At the absolute minimum this would require two lines of code.
GCD makes this fairly simple as you mentioned; I'm not sure any language would have a better way to handle this core issue. Sure, the block syntax is bad (http://fuckingblocksyntax.com); but the core fundamentals are pretty solid.
If the nesting bothers you, try moving all that UI code to a different method, and calling that method from your second nested block. You could even create a method that accepts a 'backgroundWork' selector/block and a 'foregroundWork' selector/block. However - I'd argue that the typical UI work you'd perform in such a case would be very minimal, making the extra nesting a minor inconvenience rather than an actual problem.
As far as asynchronous blocks of code that are inter-dependent, check out PromiseKit or even Sequencer; both are good options for supplementing one of Objective C's primary weakness (sequentially performed multi-threaded operations).
I haven't used it myself, but I understand that Facebook/Parse have also released another solution called BFTask, part of the Bolts framework: https://github.com/BoltsFramework/Bolts-iOS
(Or just use C#)
I have a method which encodes selected songs on iTunes to mp3 using lame. Now I'm calling it from IBAction named "Encode". While encoding, Application fails into not responding state. And when encode is finished, Application come back.
I would like to solve this not responding state. Would you teach me how should I approach?
I guess you are doing the encoding on the main thread and this is why your application becomes unresponsive. You may want to read articles about threading and concurrency in order to solve your problem.
There is also an introduction on raywenderlich.com called "Multithreading and Grand Central Dispatch on iOS for Beginners Tutorial".
You need to dispatch it on a thread different from the main thread. Otherwise it will block the main thread which is where the GUI part of your app runs.
Here is one example of how to do it. Be careful, though, if you want to modify variables outside the block. You might want to look up the __block keyword.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
// INSERT CODE HERE
});
I am modifying my program to use the new iOS5 style.
So I simply use this code:
NSManagedObjectContext *threadContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
threadContext.parentContext = [self managedObjectContextMainThread];
//threadContext.persistentStoreCoordinator= [self persistentStoreCoordinator]; //moc.persistentStoreCoordinator;// [moc persistentStoreCoordinator];
My new background ManagedObjectContext doesn't have a persistentStore but have parent store instead.\
After that I suppose I am supposed to add
performBlockAndWait on all operation where I use all operation that use the new MOC.
I don't use that and doing just fine at least so far
performBlockAndWait is done by executing the block at the same thread and wait till it's complete.
What's the difference between that and just type the code like usual?
I mean there has to be some used, but I am totally missing here.
I can understand performBlock. That'll be like executing something in back ground. Even then it's superseded with Global Central Dyspatch.
Yes there is this new thing called Queue. Okay, if we do something on the same thread, of course everything is done consecutively. Duh.... So why the queue?
Anyone care to explain?
It is possible that the thread that execute the block is not the same with the thread that call performBlockAndWait.
For example, some core data object may only be able to be executed at main thread.
Hence, the performBlockAndWait would do it on a main thread (different thread) and block the current thread.
Also it's saver. Core data would lock things up appropriately preventing collision. If you have several thread accessing the same managed object context, you need to pull this up.
The reason for performBlockAndWait: is it will get and hold the concurrency lock to access Core Data. You can consider it a modernization of the lock/unlock approach, but that's undocumented implementation detail.
If you just execute the code directly, it won't do proper concurrency locking. This is interesting for a number of reasons:
Requests to Core Data won't be properly serialized. That is, if you performBlock: (no wait) the code could end up executing at the same time as other Core Data code, which would probably cause a problem in the coordinator or persistent store.
It… well, I actually don't think it should work. It seems to most of the time in practice, but you're running Core Data without necessary locks. Pretty sure you're into undocumented behaviour here at a minimum.
So:
performBlockAndWait: sets up an environment where your block can access Core Data via the context and waits for the block to complete.
The documentation says nothing about the thread. It's not actually documented as running on the current thread.
Even if it doesn't now, it could be changed in the future to go to secondary threads in at least some circumstances.
Read the parent point again: That's what you're supposed to rely on. The rest is just details.
performBlock: sets up an environment where your block and access Core Data via the context and does not wait for the block to complete.
The documentation says nothing about the thread. It's not actually documented as running on a different thread.
Although unlikely, a future version of the OS could decide to run the block on the current thread at a later time.
Again, the parent point is what you're to rely on. The rest is undocumented details.
I hope that helps. Basically, you're supposed to play dumber than you are when touching these calls. Let the OS do the right thing, just try not to make assumptions about what it's doing. :)
The NSPrivateQueueConcurrencyType constant sets up too many expectations for how this works.
Here's my scenario: I have a thread running heavy calculations, saving the results via core data at the end. I have the thread set up with it's own autorelease pool and it's own NSManagedContext created within the thread. The user can change the inputs to the calculation on the main thread, in which case the calculation thread is terminated (via regular checks of a NSLocked variable) and relaunched with the new inputs. Everything is working fine here.
For performance reasons, the calculation thread doesn't have an undo manager and there is only one context save at the very end. If a termination command is detected I don't want to save the results. Right now I'm just skipping the context save and releasing it, which seems to work fine.
I noticed, however, that there's a reset method for NSManagedContext. Apple's documentation on this method isn't very helpful to me. It simply states that it returns the receiver's contents to it's base state and that all the receiver's managed objects are "forgotten".
What does that mean? Is it the equivalent to reverting to the last saved version? Is an undo manager required for proper operation of this method? Any reason I should use this method instead of what I'm doing now?
It sounds like you are using the context to cache changes independent of the context on the main thread, and if you don't want those changes to be recorded, you just throw them out by deleting the "local" context. This is good enough for the scenario you are describing. -reset might be useful if you didn't want to relaunch the background thread, but just start over using the same thread (and context), but with new inputs. Since you launch a new thread (thus creating a new NSManagedObjectContext on it), -reset is probably not very useful for you in this scenario. You already pretty much doing it as Apple recommends in several of their sample codes.
Was wondering if anyone knows, or has pointers to good documentation that discusses, the low-level implementation details of Cocoa's 'performSelectorOnMainThread:' method.
My best guess, and one I think is probably pretty close, is that it uses mach ports or an abstraction on top of them to provide intra-thread communication, passing selector information along as part of the mach message.
Right? Wrong? Thanks!
Update 09:39AMPST
Thank you Evan DiBiase and Mecki for the answers, but to clarify: I understand what happens in the run loop, but what I'm looking for an answer to is; "where is the method getting queued? how is the selector information getting passed into the queue?" Looking for more than Apple's doc info: I've read 'em
Update 14:21PST
Chris Hanson brings up a good point in a comment: my objective here is not to learn the underlying mechanisms in order to take advantage of them in my own code. Rather, I'm just interested in a better conceptual understanding of the process of signaling another thread to execute code. As I said, my own research leads me to believe that it's takes advantage of mach messaging for IPC to pass selector information between threads, but I'm specifically looking for concrete information on what is happening, so I can be sure I'm understanding things correctly. Thanks!
Update 03/06/09
I've opened a bounty on this question because I'd really like to see it answered, but if you are trying to collect please make sure you read everything, including all currently posed answers, comments to both these answers and to my original question, and the update text I posted above. I'm look for the lowest-level detail of the mechanism used by performSelectorOnMainThread: and the like, and as I mentioned earlier, I suspect it has something to do with Mach ports but I'd really like to know for sure. The bounty will not be awarded unless I can confirm the answer given is correct. Thanks everyone!
Yes, it does use Mach ports. What happens is this:
A block of data encapsulating the perform info (the target object, the selector, the optional object argument to the selector, etc.) is enqueued in the thread's run loop info. This is done using #synchronized, which ultimately uses pthread_mutex_lock.
CFRunLoopSourceSignal is called to signal that the source is ready to fire.
CFRunLoopWakeUp is called to let the main thread's run loop know it's time to wake up. This is done using mach_msg.
From the Apple docs:
Version 1 sources are managed by the run loop and kernel. These sources use Mach ports to signal when the sources are ready to fire. A source is automatically signaled by the kernel when a message arrives on the source’s Mach port. The contents of the message are given to the source to process when the source is fired. The run loop sources for CFMachPort and CFMessagePort are currently implemented as version 1 sources.
I'm looking at a stack trace right now, and this is what it shows:
0 mach_msg
1 CFRunLoopWakeUp
2 -[NSThread _nq:]
3 -[NSObject(NSThreadPerformAdditions) performSelector:onThread:withObject:waitUntilDone:modes:]
4 -[NSObject(NSThreadPerformAdditions) performSelectorOnMainThread:withObject:waitUntilDone:]
Set a breakpoint on mach_msg and you'll be able to confirm it.
One More Edit:
To answer the question of the comment:
what IPC mechanism is being used to
pass info between threads? Shared
memory? Sockets? Mach messaging?
NSThread stores internally a reference to the main thread and via that reference you can get a reference to the NSRunloop of that thread. A NSRunloop internally is a linked list and by adding a NSTimer object to the runloop, a new linked list element is created and added to the list. So you could say it's shared memory, the linked list, that actually belongs to the main thread, is simply modified from within a different thread. There are mutexes/locks (possibly even NSLock objects) that will make sure editing the linked list is thread-safe.
Pseudo code:
// Main Thread
for (;;) {
lock(runloop->runloopLock);
task = NULL;
do {
task = getNextTask(runloop);
if (!task) {
// function below unlocks the lock and
// atomically sends thread to sleep.
// If thread is woken up again, it will
// get the lock again before continuing
// running. See "man pthread_cond_wait"
// as an example function that works
// this way
wait_for_notification(runloop->newTasks, runloop->runloopLock);
}
} while (!task);
unlock(runloop->runloopLock);
processTask(task);
}
// Other thread, perform selector on main thread
// selector is char *, containing the selector
// object is void *, reference to object
timer = createTimerInPast(selector, object);
runloop = getRunloopOfMainThread();
lock(runloop->runloopLock);
addTask(runloop, timer);
wake_all_sleeping(runloop->newTasks);
unlock(runloop->runloopLock);
Of course this is oversimplified, most details are hidden between functions here. E.g. getNextTask will only return a timer, if the timer should have fired already. If the fire date for every timer is still in the future and there is no other event to process (like a keyboard, mouse event from UI or a sent notification), it would return NULL.
I'm still not sure what the question is. A selector is nothing more than a C string containing the name of a method being called. Every method is a normal C function and there exists a string table, containing the method names as strings and function pointers. That are the very basics how Objective-C actually works.
As I wrote below, a NSTimer object is created that gets a pointer to the target object and a pointer to a C string containing the method name and when the timer fires, it finds the right C method to call by using the string table (hence it needs the string name of the method) of the target object (hence it needs a reference to it).
Not exactly the implementation, but pretty close to it:
Every thread in Cocoa has a NSRunLoop (it's always there, you never need to create on for a thread). PerformSelectorOnMainThread creates a NSTimer object like this, one that fires only once and where the time to fire is already located in the past (so it needs firing immediately), then gets the NSRunLoop of the main thread and adds the timer object there. As soon as the main thread goes idle, it searches for the next event in its Runloop to process (or goes to sleep if there is nothing to process and being woken up again as soon as an event is added) and performs it. Either the main thread is busy when you schedule the call, in which case it will process the timer event as soon as it has finished its current task or it is sleeping at the moment, in which case it will be woken up by adding the event and processes it immediately.
A good source to look up how Apple is most likely doing it (nobody can say for sure, as after all its closed source) is GNUStep. Since the GCC can handle Objective-C (it's not just an extension only Apple ships, even the standard GCC can handle it), however, having Obj-C without all the basic classes Apple ships is rather useless, the GNU community tried to re-implement the most common Obj-C classes you use on Mac and their implementation is OpenSource.
Here you can download a recent source package.
Unpack that and have a look at the implementation of NSThread, NSObject and NSTimer for details. I guess Apple is not doing it much different, I could probably prove it using gdb, but why would they do it much different than that approach? It's a clever approach that works very well :)
The documentation for NSObject's performSelectorOnMainThread:withObject:waitUntilDone: method says:
This method queues the message on the run loop of the main thread using the default run loop modes—that is, the modes associated with the NSRunLoopCommonModes constant. As part of its normal run loop processing, the main thread dequeues the message (assuming it is running in one of the default run loop modes) and invokes the desired method.
As Mecki said, a more general mechanism that could be used to implement -performSelectorOn… is NSTimer.
NSTimer is toll-free bridged to CFRunLoopTimer. An implementation of CFRunLoopTimer – although not necessarily the one actually used for normal processes in OS X – can be found in CFLite (open-source subset of CoreFoundation; package CF-476.14 in the Darwin 9.4 source code. (CF-476.15, corresponding to OS X 10.5.5, is not yet available.)