Gcd VS Performselectorinbackground/Performselectoronmainthread

GCD vs performSelectorInBackground/performSelectorOnMainThread

When to use performSelectorInBackground:

Never. Do not use this method. It spawns an unbounded number of threads. Even before GCD was available, this was a horrible method.

When to use performSelectorOnMainThread:

Meh… Never, but just because it's inconvenient. There's nothing deeply wrong with this method. It's just not as useful as dispatch_async().

The difference between GCD and the old performSelector… methods (and NSThread in general) is that GCD manages a thread pool for you. In general, you should avoid manual threading in Cocoa. Instead, use NSOperationQueue or GCD (dispatch methods). They provide a more useful queue abstraction rather than forcing you to manually manage threads.

Be sure to read over Apple's Migrating Away from Threads for more info.

Replacing performSelectorInBackground with GCD

You use dispatch_async like suggested.

For example:

    // Create a Grand Central Dispatch (GCD) queue to process data in a background thread.
dispatch_queue_t myprocess_queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

// Start the thread

dispatch_async(myprocess_queue, ^{
// place your calculation code here that you want run in the background thread.

// all the UI work is done in the main thread, so if you need to update the UI, you will need to create another dispatch_async, this time on the main queue.
dispatch_async(dispatch_get_main_queue(), ^{

// Any UI update code goes here like progress bars

}); // end of main queue code block
}); // end of your big process.
// finally close the dispatch queue
dispatch_release(myprocess_queue);

That's the general gist of it, hope that helps.

why using NSOperation, GCD or performSelectorInBackground I can't take snapshot of UIView?

You must take screenshots on the main thread. This is the only thread where the UI is stable.

If you have problems for several seconds, I suspect you have some other problem going on that this is just exposing. The most likely is other UIKit calls you're making on background threads. That's not supported and would lead to the symptom you describe.

performSelectorInBackground with more that 2 parameters

Why don't you use Grand Central Dispatch?
You could do something like:

static TestClassCallback savedCallback;
- (void)doSometginh:(Book*)aBook callback:(ClassCallback)aCallback {
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
[self doVeryLongTask1:aPerson callback:aCallback];
});
}

You can perform the callback in the main thread with this code:

dispatch_async(dispatch_get_main_queue(), ^(void){
callback();
});

EDIT:
Those calls can be nested.
For example if you want to have Task1 and Task2 that run in the background and you want to update something on the mainthread between them:

dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
// Task 1
dispatch_async(dispatch_get_main_queue(), ^(void){
// Update on main thread
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
// Task 2
});
});
});

Add another call of dispatch_async(dispatch_get_main_queue(), ^(void){ after // Task 2 to add a final callback on the mainthread.

What's the difference between performSelectorOnMainThread: and dispatch_async() on main queue?

By default, -performSelectorOnMainThread:withObject:waitUntilDone: only schedules the selector to run in the default run loop mode. If the run loop is in another mode (e.g. the tracking mode), it won't run until the run loop switches back to the default mode. You can get around this with the variant -performSelectorOnMainThread:withObject:waitUntilDone:modes: (by passing all the modes you want it to run in).

On the other hand, dispatch_async(dispatch_get_main_queue(), ^{ ... }) will run the block as soon as the main run loop returns control flow back to the event loop. It doesn't care about modes. So if you don't want to care about modes either, dispatch_async() may be the better way to go.

call performSelectorOnMainThread after performSelectorInBackground?

Can't we apply our results from a 'detached' thread?

No, the UI can not be updated from other than the main thread. In general, UIKit is not thread-safe.

For the most part, UIKit classes should be used only from an
application’s main thread. This is particularly true for classes
derived from UIResponder or that involve manipulating your
application’s user interface in any way.

This is why it is a common practice to perform a long running task in the background and then call performSelectorOnMainThread to update the UI.

Although beginning with iOS 4.0, drawing to a graphics context in UIKit is thread-safe. Specifically, accessing and manipulating the current graphics stack, drawing images and strings, and usage of color and font objects from secondary threads.

Difference between calling a function in background and using calling a function in thread

They're identical. See Documentation

performSelectorInBackground:withObject: The effect of calling this method is the same as if you called the detachNewThreadSelector:toTarget:withObject: method of NSThread with the current object, selector, and parameter object as parameters.

Hope it helps.

Is it safe to use GCD to open a socket connection on iOS, even with a complex stack?

First off, I agree with the other answer: Don't use -performSelectorInBackground:withObject:. Ever.

Next... you said:

The alternative, GCD and NSOperationQueue, both appear to persist the
full stack frame, including 4! separate context switches, when I pause
my app in the debugger. Therefore, if I open a socket connection
inside a particular deep stack, that stack will persist for the
lifetime of my app.

Are there any downsides to this?

Short answer? No. There are no downsides to this.

Long answer:

You appear to be mistaking debugging features for reality. In your screen shot there, those dotted lines aren't "context switches" (for any definition of 'context switch' that I'm aware of.) Xcode is eliding frames from the stack that it believes are not of interest to you (i.e. aren't in your code, or crossing into/out of your code.) You can toggle this behavior with the leftmost control in the bottom bar.

The "Enqueued from" stack traces are historical information aimed at helping you understand what caused the current (i.e. top) stack trace to happen. They're not execution states that still exist. They're just debugging information. You can safely assume that there's no "cost" to you associated with this.

The notion that opening a socket somehow causes a stack to "persist for the lifetime of [your] app" also doesn't make any sense. A socket is just a data structure in memory with some associated behavior provided by the OS. You're thinking about this too much.

Lastly, do yourself a favor, and don't choose APIs based on what makes your debugger stack traces look "nicer/cleaner/better."



Related Topics



Leave a reply



Submit