performSelectorOnMainThread and waitUntilDone, for NSURLConnection - objective-c

I am not clear about what does waitUntilDone do, but I found this thread:
What is the significance of WaitUntilDOne in performSelectorOnMainThread?
which makes me a bit clear, however, if I perform some selector which makes NSURLConnection(which is asyncrhonous) and waitUntilDone set to YES, what will happen then? It will wait for the method to execute, but the method actually does some asynchronous operation(ie NSURLConnection), then what is the impact?
Thanks!

NSURLConnection is asynchronous. Your code runs on the main thread, and it makes delegate calls to you as the download progresses. You don't need to, and should not, run an NSURLConnection from a background thread.
If you DO have code that needs to run on a background thread, you can use the preformSelectorOnMainThread method to send messages from your worker thread to the main thread. One common reason to do this is that you can't update the UI from a background thread. You'd invoke a method to update the UI on the main thread.
The flag waitUntilDone controls what happens after the performSelectorOnMainThread call. If waitUntilDone is false, your background thread continues on with the next line without waiting for the code on the main thread to finish.
If waitUntilDone is true, your background thread will block until the main thread finishes performing the selector that you sent it.

Related

UISegmentedControl setTitle:forSegmentAtIndex:, explicit dispatch to main thread needed?

I have a notification which can be posted on a background thread. This notification eventually leads to calling setTitle:forSegmentAtIndex:, which is UISegmentedControl, part of the UIKit.
Should it be assumed that I need to wrap this setTitle:forSegmentAtIndex: call with a async call to main thread, or will some lower lying Cocoa code automatically dispatch anything like setTitle:forSegmentAtIndex: to the main thread?
Always dispatch code that modifies a UI control to the main queue. Always.

Long lived thread doesn't call performSelectorOnMainThread

I have a worker thread that I keep alive through a loop that's controlled by a flag. I need the thread to stay alive for the length of my application as it opens a permanent connection to a remote server.
I fire up that thread and call several methods on it with:
[worker performSelector:#selector(getBusy) onThread:worker withObject:nil waitUntilDone:NO];
This seems to work fine and the method is called. At some point in getBusy I try to call a method in the main thread with:
[delegate performSelectorOnMainThread:#selector(gotBusy) withObject:nil waitUntilDone:NO
where delegate is a reference to the class that starts the separate thread.
The problem is that gotBusy never gets called on the main thread. I've peppered it with NSLog() statements and I can't see them printed on the console.
What should I be looking for to debug this?
First, make sure delegate is not nil. Secondly, make sure your main event loop is not blocked and not running in a modal mode.
Is it possible that you never assigned delegate, so you're calling performSelectorOnMainThread on a nil object? You could try setting waitUntilDone to YES so your worker thread will block and let the delegate do its work.

NSOperationQueues in Objective C

I am new to programming. I am porting cpp (WIN32) to cocoa framework. I have a method called start(process) from where 2 methods gets called. I want to do the operation in it parallely.I want to do InterThread communication.
This can be done by performSelectorOnMainThread:withObject:waitUntilDone.
Here I need to call the 2nd thread first and the 1st thread is called second.The 2nd thread waits for the 1st thread's signal.(eg:1st thread does addition of two no's and 2nd thread does the display and some other operations)
[receiverobj performSelectorOnMainThread:withObject:waitUntilDone]
is the syntax for doing it.But both of them are instance methods of the same class.And the 1st threads return type is a void value and the 2nd threads return value is uint8_t. How to receive the signal from the 1st thread onto the second thread which has begun its execution just before the 1st Thread.
The first thing about Cocoa is that all display code should run on the main thread. So if you are asking how to let the main thread know it needs to do some display work, performSelectorOnMainThread:waitUntilDone: is the right answer. This method works by putting an artificial "event" in the main thread's run loop (the loop that processes events from the UI and timers etc). The receiver will invoke the method exactly as if you had called it directly but it will happen on the main thread.
If you want to signal another thread that the display work has finished, you can do it synchronously like this:
[receiver performSelectorOnMainThread: #selector(mySelector) withObject: nil waitUntilDone: YES];
The calling thread will then pause until the method has finished.
If you just want to fire and forget it's
[receiver performSelectorOnMainThread: #selector(mySelector) withObject: nil waitUntilDone: NO];
The pattern is generalisable to any thread with the method performSelectorOnThread:withObject:waitUntilDone:. However, if you do this, you must make sure the target thread is executing a run loop.

Cancelable loading in background thread

I have a window that displays some data in an NSTableView. This data is loaded in the background. The data-loading-thread is started in the windowDidLoad: method. If the window is closed before loading has finished, the background thread should be cancelled. I do this by signalling the thread in the windowWillClose: delegate method and waiting for the background thread to finish.
Now this all works perfectly. But I have one problem: How can I update the data in the table view? I have tried calling reloadData via performSelectorOnMainThread: but this leads to a race condition: The reloadData call is sometimes queued on the main thread after the window close command, and will execute after the window has closed, and everything goes up in flames.
What's the best way to control and communicate with a background thread?
Well, you know, this is exactly what makes the use of threading complex: you always face synchronization issues.
What I suggest is, instead of calling [tableView reloadData] from your thread, simply signal your controller (by calling a method controllerShouldReloadTable) and let your controller do the check if windowWillClose has been called or not. There might be a chance that your controller has been also released by the time controllerShouldReloadTable, and to fix this you will definitely need to retain the controller from the secondary thread.
On a side note, I would cancel the thread in viewDidUnload (for symmetry).
Most important: I would use asynchronous calls and a delegate class so that the whole multithreading issue is solved at its root.
EDIT: Sending asynchronously a request will not block the sending thread waiting for the response. Instead, asynchronous send (for NSURLConnection is called start) immediately returns (so, no blocking) and when the response is received, a delegate method will be called (i.e., connectionDidFinishLoading:) so that you can updated the model and the UI. Take a look at NSURLConnection docs, but as usual, I strongly suggest using [ASIHTTPRequest][2], which has many advantages.

Cocoa - NSThread and First Responder

When I start a 2nd background thread and pause the main thread, will my First Responder still be in action? For example I have an overwriting method called -flagsChanged and was wondering if it would still be active if the main thread is offline.
Thanks,
Kevin
Don’t pause the main thread since the main thread is responsible for handling events and your application UI will become irresponsive. If the main thread is paused, it won’t handle events, hence it won’t dispatch key events to the first responder.
If you think you need to pause the main thread, you probably need to redesign your program so that the behaviour that requires sleeping (if it does require sleeping) is offset to a secondary thread. If you need to update the user interface from a secondary thread, you should use -performSelectorOnMainThread:withObject:waitUntilDone:.