How does multithread work in objective-c? - iphone

In the scenario in which i have a thread launched, can i still acces methods on the parent thread? Is there a specific way to call this methods? If so, what is it?
Note: in my scenario both thread are for data manipulation, they are not interface-related threads ( i know this was to be considered in .NET, don't know it they are in Objective-c).

In this case, it is best to use Grand Central Dispatch (GCD) instead of working with NSThead or NSOperation directly.
Overview of Concurrency: http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008091
Intro to Grand Central Dispatch: http://cocoasamurai.blogspot.com/2009/09/guide-to-blocks-grand-central-dispatch.html
With your example, you can use nested calls into Grand Central Dispatch to achieve this functionality:
dispatch_queue_t backgroundQueue = dispatch_queue_create("com.example.exampleQueue", 0);
dispatch_async(backgroundQueue, ^{
// operate on data in the background here
NSData *stuff = [self doSomethingComplex];
dispatch_async(dispatch_get_main_queue(), ^{
// Perform Task back in the main thread
[viewController updateStuff:stuff];
});
});
This method is the preferred method for performing these kind of tasks. In addition, by utilizing blocks, it is also very easy to understand the code at a glance without having to example multiple methods within your class.

Threads by definition share the state of parent thread. In ObjectiveC, if you spawn a worker thread & want to call some method on main thread, this can be done like so-
[self performSelectorOnMainThread:#selector(someMethod:) withObject:nil waitUntilDone:NO];

If they are not interface stuff, or can result in some interface stuff you can call then you can just call then, and do any of the usual thread safety stuff you have to do in any language, like #syschronise(obj) or NSLock. But if it is stuff that will result in interface stuff then you will have to do as 'Srikar' wrote [self performSelectorOnMainThread:#selector(setDataCount:) withObject:count waitUntilDone:NO]; which will effectively place the message onto the NSRunLoop cue.

Related

running operation in background thread and have a completion block?

I have a task which is reading from a disk, potentially going to take quite some time, so don't want to do it in a main thread.. and what I want is to call a function X after reading from the disk. What is the best way to do this in iOS?
So far this is what I've tried:
NSInvocationOperation *processDataOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:#selector(readDisk:) object:nil];
[processDataOperation setQueuePriority:NSOperationQueuePriorityVeryHigh];
[processDataOperation setCompletionBlock:^(void){
NSMutableArray *feedItemsArray = [self generateFeedItemsFromDictionary:streamDiskData];
[self postFetchCompletedNotificationForDict:queryStringDict withFeedItems:feedItemsArray isFresh:NO];
}];
basically I am using NSInvocationOperation and then set it's completion block, however the issue is that in my completion block I need the result that is generated in readDisk. How do I access that in the completion block? It's nearly imposible right?
Using NSInvocations it is possible, but far more complicated than necessary, to achieve a trivial amount of work beyond the main thread.
Both GCD and NSOperations can be used to implement a wide array of concurrency strategies. From an object-oriented perspective, NSOperations are more highly abstracted than CGD blocks, which makes them (imo) easier to "design" with, and potentially optimized beyond the scope of where I'm implementing them. GCD is lower-level: This makes interacting with it appear slightly more complicated (it really isn't), but people who are in to that sorta stuff will tell you that it is "more efficient" and carries "less overhead".
My personal approach is to use NSOperations in scenarios where I have a designed/orchestrated concurrency pattern in my application, and use GCD for trivial concurrent/background operations.
If all I need to do is fire some arbitrary task that is not relevant to the design but needs to be done in the background, I'd use CGD. That's what I'd probably use in this case:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
[self readDisk];
NSMutableArray *feedItemsArray = [weakSelf generateFeedItemsFromDictionary:streamDiskData];
dispatch_sync(dispatch_get_main_queue(), ^{
//Call back to the main thread before performing/posting anything touching UIKit
[self postFetchCompletedNotificationForDict:queryStringDict withFeedItems:feedItemsArray isFresh:NO];
})
})];
You could always use grand central dispatch to do your operation in the background instead.
Since it is a block you can just call the method normally and store the result. Then grab the main queue if you need to update any UI or do whatever you need to after completion.
dispatch_queue_t queue = dispatch_queue_create("read disc", NULL);
dispatch_async(queue, ^{
result = [self readDisc];
dispatch_async(dispatch_get_main_queue(), ^{
//update UI or do whatever you need to do with the result of readDisc
});
});
dispatch_release(queue);

iOS : Best way to organise multithreading

Guys I need some help to architect my multithreading in iOS.
I'm using ARC in my code.
So basically I need following,
In my main thread nstimer fire some method which should be executed in a separate thread, that thread does some calculation and puts data into some ivar, and another thread should read data from that ivar and do some other calculation, i.e. if there is no data the second thread should wait until there is any.
So basically I would like to hear some advice which technology is the best choice for my task, to use cocoa thread (NSThread), GCD or Operation queues.
Also can someone please provide me with some pseudo code on aspects of mutual blocking/synchronization between two threads.
Since you are saying that some calculations should wait for other calculations to finish, I would say that you should have a look at NSOperation and set dependencies for the different operations (using addDependency).
Unless you left something our of your problem description, that is a perfect fit for GCD/block combo. In fact, I wouldn't even use a NSTimer (GCD provides a better alternative - see dispatch_source_create for example of creating GCD based timer), but that's your call, and not what the question asked. Anyway, with GCD...
- (void)handleTimer:(NSTimer *)timer {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
__block id someObject;
// Do work... manipulate someObject in some manner...
// When done, invoke other thread... main thread in this case
dispatch_async(dispatch_get_main_queue(), ^{
// This code is running in a different thread, and can use someObject directly
});
});
}

Worker Thread iOS

I want to create a background thread on the iPhone that executes some code every 10msec.
But before I get lost in the concurrency programming guide and the threading programming guide of apple again, I wanted to ask whether someone here can help me out.
What I want to do:
Create a background worker thread
Trigger the execution of a method every 10msec. (probably by using a NSTimer in that thread?)
Put as less load on the main application thread as possible
In my understanding subclassing NSThread and writing my own main method in that subclass should do the trick. That way I don't use an NSTimer for the update intervals but something like:
[NSThread sleepForTimeInterval: 0.01];
Also queuing mechanisms between main thread and worker thread don't make any sense, as the worker thread should perform the same operation over and over - until stopped.
The question is: How can I configure the thread to use a timer? I can't see how I can attach a NSTimer to that worker threads Run Loop?
It's possible to do this using the method you outline, but have you looked at using Grand Central Dispatch? It can make some of this a lot easier:
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(backgroundQueue, ^{
while ([self shouldKeepProcessingInBackground]) {
[self doBackgroundWork];
usleep(1e4);
}
})
You can also use a timer dispatch source to do work periodically:
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_source_t timerSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, backgroundQueue);
dispatch_source_set_timer(timerSource, dispatch_time(DISPATCH_TIME_NOW, 0), 0.01*NSEC_PER_SEC, 0*NSEC_PER_SEC);
dispatch_source_set_event_handler(timerSource, ^{
[self doBackgroundWork];
});
dispatch_resume(timerSource);
NSRunLoop is the missing link.
You will have to setup the thread's run loop to repeat, or you can control this from your thread's entry. the thread hosts the timer (the timer will die with the run loop if it's still alive).
NSRunLoop is a pretty small class - check it and the related samples out.
You could easily use GCD (grand central dispatch) for that. First create a selector that will be called in the background. From here call whatever method you want.
- (void)backgroundSelector
{
// do whatever you want to do
[self performSelector:#selector(backgroundSelector) withObject:nil afterDelay:0.01];
}
After that just fire this method for the first time like this
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
[self backgroundSelector];
});
Let me know if that works for you.
It is pretty simple and clean if you do it with NSThread. With no need to subclass it.
- (void)backgroundStuff {
while (!self.cancelThread) {
// do your work
[NSThread sleepForTimeInterval:0.01];
}
}
Just an ordinary function. cancelThread is a member variable you declare. Start it with
[NSThread detachNewThreadSelector:#selector(backgroundStuff) toTarget:self withObject:nil];
and you can cancle the thread anytime with self.cancelThread = true;

performSelectorOnMainThread with multiple parameter

I am trying to perform this action on the main thread:
[curItem.mButton setBackgroundImage:newArt forState:UIControlStateNormal];
So I do this...
cWrapperObject* obj = [cWrapperObject alloc];
[obj setupParams :curItem.mButton :newArt];
[obj performSelectorOnMainThread:#selector(setImageForButton) withObject:nil waitUntilDone:YES];
I feel like this is bad, does anyone has any suggestions on how I could approach this differently?
Another option is GCD. You can invoke a block on the main queue which gets run serially when the run loop runs. blocks aren't limited to one object like performSelectorOnMainThread.
dispatch_async(dispatch_get_main_queue(), ^{
// code here
});
I wrote a more comprehensive comparison of performSelectorXXX and GCD here complete with samples:
GCD, Threads, Program Flow and UI Updating
Also, here's another related SO post:
GCD to perform task in main thread
If you need to pass only one parameter, you should set up "withObject:" argument in method performSelectorOnMainThread:withObject:waitUntilDone. So your method should be declared as
-(void)setImageForButton:(id)parameter
and you should invoke method on main thread with:
[obj performSelectorOnMainThread:#selector(setImageForButton:) withObject:newArt waitUntilDone:YES];
Note ':' in #selector(setImageForButton:) this means that this method will be messaged with one argument, passed in withObject:

Objective-C : Start an object on a background thread -- interact as usual?

I would like to have an object be callable from the main thread
MyObj* backgroundObject = [[MyObj alloc] initInBackground];
BOOL result = [backgroundObject computeResult];
But have all the methods of backgroundObject compute in another thread.
And also have backgroundObj be able to send messages to it's delegate. How can I do such a thing? Is it possible?
As others have pointed out, an NSObject doesn't exist on any one thread, a thread only comes into play when you start executing its methods.
My suggestion would be to not use manual threads for every time that a method is called on the object, but instead use NSOperations and an NSOperationQueue. Have an NSOperationQueue as an instance variable of the object, and have calls to the various methods on the object create NSOperations which are inserted into the queue. The NSOperationQueue will process these operations on a background thread, avoiding all of the manual thread management you would need to have for multiple accesses to methods.
If you make this NSOperationQueue have a maximum concurrency count of 1, you can also avoid locking shared resources within the object between the various operations that will be performed on a background thread (of course you'll still need to lock instance variables that can be accessed from the outside world).
For callbacks to delegates or other objects, I'd recommend using -performSelectorOnMainThread:withObject:waitUntilDone so that you don't have to think about making those delegate methods threadsafe.
See the Concurrency Programming Guide for more.
Sure, you can use NSThread for that, and have backgroundObject use performSelectorOnMainThread: to contact the delegate.
NSThread documentation
performSelectorOnMainThread:withObject:waitUntilDone:
Objects do not exist in threads AFAIK. The function you send to an object will always be performed on the thread you sent it from (unless you use NSThread or performSelectorOnMainThread or something along those lines).
What you need is a NSOperation and a block/delegate parameter to notify the caller of completion.
Look at the documentation of NSOperation and NSOperationQueues
You should use GCD:
/*
* I didn't initalised your object in background, because
* because in the most cases you need your object to stick around
* and only perfom the time consimung calculations in background
*/
MyObj* backgroundObject = [[MyObj alloc] initInBackground];
...
- (void)startBackgroundTask {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//in a perfectly async non blocking block :-)
BOOL result = [backgroundObject computeResult];
dispatch_async(dispatch_get_main_queue(), ^{
//post your result, or do something else with your result
[[NSNotificationCenter defaultCenter] postNotificationName:"backgroundComputeResultDone" object:[NSNumber numberWithBool:result]];
if (result) {
//do some stuff
}
});
});
}
Maybe you can take a look at these two videos from apple here:
WWDC 2011 - Session 210 - Mastering Grand Central Dispatch
WWDC 2011 - Session 308 - Blocks and Grand Central Dispatch in Practice