Modal alert in background thread in iPhone - iphone

In my iPhone app, main thread creates a background thread which does a lot of work and in some cases needs to ask user for their decision. When user is asked the question, background thread should stop working and should continue only after user has answered question.
What is the best way to do it?
P.S.
I've tried ModalAlert from iPhone Developer's Cookbook, which was said to do the trick, but I have not succeeded. It seems like CFRunLoopRun (which is supposed to stop thread from executing) just does not stop the background thread.
I had code like that
+(void) main
{
[NSThread detachNewThreadSelector:#selector(startSync) toTarget:self withObject:nil];
}
+(void) startSync
{
CFRunLoopRun();
NSLog("Hi");
}
and NSLog was just immediately executed after start of syncStart thread. Weird.

Have you tried NSObject's performSelectorOnMainThread:withObject:waitUntilDone: method?
Present your question to the user on the main thread, then store the response somewhere where your background thread can access it. Also, you should be able to block your background thread for the duration that your main thread selector runs by setting YES to the waitUntilDone: parameter.

Related

How can I cancel an NSOperation in the same thread that the operation?

When I cancel an NSOperation (when user presses a button) cancel method is called from the main thread, but evidently the operation is running in another thread.
So, to avoid race conditions when I change _isExecuting and _isFinished, I think cancel (or at least its logic) should be called from the same thread that the NSOperation. Apart from that, when user cancels it, several files are deleted and it takes time. Because cancel is called from main thread, all the app becomes unresponsive for a while, which is ugly.
How can I execute cancel code in the same thread that the current NSOperation?
I tried this in cancel (similar to what I saw in ASIHTTPRequest):
if (_operationThread) {
[self performSelector:#selector(cancelOnRequestThread) onThread:_operationThread withObject:nil waitUntilDone:NO];
} else {
[self cancelOnRequestThread];
}
And _operationThread is setted in start method using:
_operationThread=[NSThread currentThread];
But it doesn't work.
Any idea or suggestion?
Note: I use concurrent operations, so I use start instead of main.
Thanks a lot for help.
Ricardo.
It's fine to call cancel on an NSOperation from the main thread. The cancel method is thread-safe.
That shouldn't cause any blocking on your main thread because the cancel method itself shouldn't be doing any work. If you have overridden the cancel method of your operation to delete files, etc then that is the wrong approach. You shouldn't override the cancel method, instead just check the isCancelled method at regular points within the operation's main method (e.g. inside any tight loops) and then return from main early if isCancelled returns YES, which will then cancel the operation on the same thread as the rest of the execution.
If that's how you've implemented it already and you're still having performance issues, is it possible that your operation is not really running on a background thread at all? For example if you've added it to the queue returned by [NSOperationQueue mainQueue] then that's actually running on the main application thread.

how to cancel the background running thread in my iphone app

i wrote like:
[self performSelectorInBackground:#selector(backgroundImageLoading) withObject:nil];
to load image background but know i need to stop this when i refresh the view but i don't have any idea how to do
See NSOperation and NSOperationQueue.
Its also to do the process concurrently as like background thread. Here in NSOperation you have cancel method available to stop the operation.
The threads should not be forced to kill. look out the reasons here. It may help you to find the solution.

Main thread doesn't respond while NSOperationQueue is running its task

I use NSOperationQueue to create UIImages in the background,
upon image creation, main thread gets notified and set the image to a view.
While it works and all, main thread is not responding as I hoped while the NSOperationQueue is working.
The point of using thread here is to let UI be responsive to user interactions.
Am I missing something here?
check Invoking thread with a single parameter

iphone - what is the logic of this kind of multithread operation

I am just trying to understand this: multithread is a way of firing a method in another thread, so it will not hang the main thread (when something heavy must be done). But I have seen stuff like this:
this goes on the main code:
[NSThread detachNewThreadSelector:#selector(createNewThread) toTarget:self withObject:nil];
and here goes the thread
-(void) createNewThread {
NSAutoreleasePool* p = [[NSAutoreleasePool alloc] init];
[self performSelectorOnMainThread:#selector(doSomeStuff) withObject:nil waitUntilDone:YES];
[p release];
}
My problem with this is: if the thread is intended to relieve the main thread from doing something, why is doSomeStuff being called using performSelectorOnMainThread? Isn't that insane? I mean, you fire a second thread just to run something on the main thread, a thread that in fact you shouldn't be using.
I have seen a lot of code on the web write this way.
I know that probably it is done that way because it is doing something that is not thread safe, but is doing this really useful? To me sounds that it is totally useless and it would be better to do something like
[self performSelector:#selector(doSomeStuff) withObject:nil afterDelay:0.01];
what do you guys think?
thanks in advance.
performSelectorOnMainThread:withObject:waitUntilDone: puts the call on a queue to perform on the next iteration of the run loop. performSelector:withObject:afterDelay: sets up a timer to perform the action. However, creating a new thread to call performSelectorOnMainThread makes no sense because it puts the call on the queue even if it is already on the main thread.
If that's the entire body of the createNewThread method then it makes no sense. But if other stuff actually happens in createNewThread then there might be a good reason. The most common scenario for having a background thread use performSelectorOnMainThread: is if the UI needs to update as a result of the background activity. Like if you're processing a large data set and you want to show the user how much progress has been made so far. UIKit is not thread-safe so you can't update the UI from the background thread. But you might do something like, have the background doing a lot of work in a loop, and at every pass through the loop (or every 5, or whatever) call back to the main thread to update the UI. This makes the code switch back to the main loop just long enough to update the UI before returning to the background for the heavy duty work.

iPhone SDK Background threads calling other methods

I am a seemingly straightforward question that I can't seem to find an answer to (and it is hindering my app).
I have a background thread running a paricular method:
-(void)processImage:(UIImage *)image {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//Process image here in the background here
[pool drain];
}
This much works great, but my question comes when I want to call another method from inside the already-background method. Does this call stay in the background? Do I need to add NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; and [pool drain]; to the new method to make it run in the background as well?
Any advice would be very helpful. I am a bit confused about this.
Many thanks,
Brett
It WILL stay in the background, on the same thread it was called from.
Some threading notes to consider with this:
It may not be obvious, but if you call a timer from the background thread, and the thread exits before the timer is supposed to go off, the timer will NOT be called. Thus it is recommended you setup timers from the main thread
You dont need another autorelease pool unless you spawn another thread.
Any UI updates should be done on the main thread
You don't need to add yet another autorelease pool, the one you already have is enough. And yes, all calls that you make that originate from that thread stay in that thread and thus also run "in the background". Exception would be the use of "performSelectorOnMainThread:", which of course makes the given selector to be performed on the main thread :-) If you want to call GUI methods (like setting the image on an UIImageView) you should make sure to do so on the main thread. See the docs for "performSelectorOnMainThread:waitUntilDone:" (sorry for not giving you you the links, am typing this on my iPad).