how to create multyple threads in iphone(in single class)
please help me with sample code.
Check out the documentation for NSThread, NSOperationQueue, and the various performSelector... methods defined for NSObject.
NSThread Class reference
An example to run a child thread:
- (void)threadRun
{
// One thread, one autorelease pool. as main thread's pool inside main.c
NSAutoreleasePool *aPool = [[NSAuroreleasePool alloc] init];
// do-job in thread here
[aPool release];
}
- (void)performJobWithThread
{
// Method 1:
NSThread *aThread = [[NSThread alloc] initWithTarget:self
selector:#selector(threadRun)
object:nil];
[aThread start];
/// Release aThread at some point avoid memory leak.
// Method 2:
[NSThread detachNewThreadSelector:#selector:#selector(threadRun)
toTarget:self
withObject:nil];
}
Before using NSThread, it's better to read Threading Programming Guide first. It will tell you about memory management, communication with other thread, ..., etc.
NSOperation and NSOperationQueue are good to design multithread. But I am learning them now and I am unable to talk about them clearly.
Related
I am new to asynchronous callbacks and have been given differing advice. I need to perform asynchronous callbacks and after many hours of research I still do not know if I should use blocks or GCD and queues. Any pointers would be welcome.
OK. So what I was really asking is:
"in order to use an 'asynchronous' callbacks, do I need to use GCD and queues?"
What I am gathering from the answers is that the answer is YES. Definitely GCD and queues inside of blocks.
My confusion stemmed from the fact that I had been given the direction that all I needed was a block, like the code below:
[UIView animateWithDuration:.4f
animations:^{
flashView.alpha = 0.f;
}
completion:^(BOOL finished){
[flashView removeFromSuperview];
}
];
But what I am seeing in the answers here is that the above block in not sufficient for making 'asynchronous' callbacks. Instead I DO in-fact need to use GCD and queues inside a block, like the code below:
- (void)invokeAsync:(id (^)(void))asyncBlock resultBlock:(void (^)(id))resultBlock errorBlock:(void (^)(id))errorBlock {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
id result = nil;
id error = nil;
#try {
result = asyncBlock();
} #catch (NSException *exception) {
NSLog(#"caught exception: %#", exception);
error = exception;
}
// tell the main thread
dispatch_async(dispatch_get_main_queue(), ^{
NSAutoreleasePool *secondaryPool = [[NSAutoreleasePool alloc] init];
if (error != nil) {
errorBlock(error);
} else {
resultBlock(result);
}
[secondaryPool release];
});
[pool release];
});
}
An asynchronous callback is one where your current thread keeps executing statements, and you detach the execution of code in a different thread to be ran later.
There are several technologies to accomplish this. On this example I'm calling the method cacheImage:, with parameter image (just an example) in 4 different asynchronous ways.
// 1. NSThread
[NSThread detachNewThreadSelector:#selector(cacheImage:) toTarget:self withObject:image];
// 2. performSelector...
[self performSelectorInBackground:#selector(cacheImage:) withObject:image];
// 3. NSOperationQueue
NSInvocationOperation *invOperation = [[NSInvocationOperation alloc] initWithTarget:self selector:#selector(cacheImage:) object:image];
NSOperationQueue *opQueue = [[NSOperationQueue alloc] init];
[opQueue addOperation:invOperation];
// 4. GCD
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self cacheImage:image];
});
By far the more simple way is to use GCD because it already has a thread ready for you to use, instead having to create it yourself with the other options.
However, because blocks are implemented as objects, you could indeed use blocks without GCD, for example:
// block definition
typedef void (^hello_t)();
// method that uses a block as parameter
-(void) runBlock:(hello_t)hello {
hello();
}
// asynchronous execution of a block
[NSThread detachNewThreadSelector:#selector(runBlock) toTarget:self withObject:^(){
NSLog(#"hi");
}];
PS: you don't need to use NSAutoreleasePool manually unless you create many many objects and you want to free memory immediately. Also, #try #catch are rarely used in Objective-C
Not any point of confusion here. GCD also has a block execution.
GCD API, which supports the asynchronous execution of operations at the Unix level of the system.
Block objects are a C-level syntactic and runtime feature. They are similar to standard C functions, but in addition to executable code they may also contain variable bindings to automatic (stack) or managed (heap) memory. A block can therefore maintain a set of state (data) that it can use to impact behavior when executed.
Apple designed blocks with the explicit goal of making it easier to write programs for the Grand Central Dispatch threading architecture, although it is independent of that architecture and can be used in much the same way as closures in other languages. Apple has implemented blocks both in their own branch of the GNU Compiler Collection and in the Clang LLVM compiler front end. Language runtime library support for blocks is also available as part of the LLVM project.
Therefore you can use any one of them given you same functionality.
My application has a second running thread. I need to achieve the following :
Stop the separate thread gracefully from the main application thread
Call a function on the main thread from the second thread to signal a result has been found and pass it to the main one.
I've found the following for the first task : share a global variable between the 2 threads ?
No idea how to achieve the second task. (NSNotificationCenter doesn't allow to pass objects ...)
I'm lunching the second thread like this [NSThread detachNewThreadSelector:#selector(backGroudTask) toTarget:self withObject:nil];
Thanks
I'm still searching for the best answer to this, but here is what I do:
Use NSLock to create a lock that prevents me from accessing the same variable on both threads. Then use a BOOL to see if the main thread wants to initiate a stop.
in main thread do this
[myLock lock];
exitFlag = YES;
[myLock unlock];
in the other thread do this
endMe = NO;
while(!endMe)
{
// do your task stuff
[myLock lock];
endMe = exitFlag;
[myLock unlock];
}
For the second part of your question use the following:
[self performSelectorOnMainThread:#selector(your_selector_name) withObject:nil waitUntilDone:false];
This will cause the your selector routine to run on the main thread.
Hope this helps
(NSNotificationCenter doesn't allow to pass objects ...)
it does, but you have to add them to the userinfo of the notification
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:myObject forKey:#"object"];
[[NSNotificationCenter defaultCenter] postNotificationName:#"myNotification" object:self userInfo:userInfo];
- (void)foo:(NSNotification *)notification {
id object = [[notification userInfo] objectForKey:#"object"];
}
Is there a clean way of joining threads in Objective C much like "Thread.join" in Java? I found the method performSelector:onThread:withObject:waitUntilDone: but the limitation of this is I can't call the "blocking" on a different line because I want to do something like this:
[dispatch Thread A];
[process something on main thread];
[wait for Thread A to finish before proceeding];
Thank you in advance.
I'm not aware of any Cocoa API to do this, but it wouldn't be too difficult to do with NSThread, pretty easy to do with a lock, and even easier to do with Grand Central Dispatch.
NSThread
NSThread * otherThread = [[NSThread alloc] initWithTarget:self selector:#selector(methodToPerformInBackground:) object:aParameter];
[otherThread start];
//do some stuff
while ([otherThread isFinished] == NO) {
usleep(1000);
}
[otherThread release];
NSLock
NSLock * lock = [[NSLock alloc] init];
//initiate the background task, which should immediately lock the lock and unlock when done
//do some stuff
[lock lock]; //this will pause until the background stuff unlocks
[lock unlock];
[lock release];
Grand Central Dispatch
dispatch_group_t myGroup = dispatch_group_create();
dispatch_group_async(myGroup, dispatch_get_global_queue(), ^{
//stuff to do in the background
});
//do some stuff
dispatch_group_wait(myGroup, DISPATCH_TIME_FOREVER);
dispatch_release(myGroup);
NSConditionLock is the answer to my question, Sorry Dave DeLong, but I cannot use:
"while ([otherThread isFinished] == NO) "
-- because I need fast continuous processing and cannot use sleep.
NSLock
-- because as you said it "initiate the background task, which should immediately lock the lock and unlock when done", this is not a solution because I tried it and we are not sure if the subthread will execute last before the lock-unlock-release on main thread, I ended up getting random errors.
Grand Central Dispatch
--because it's only available in IOS4 and Snow Leopard 10.6, I'm using a lower version.
But your answer gave me the idea and thank you very much for it, so I just "upped" you.
I ended up doing this:
#define T_START 0
#define T_FINISHED 1
-(void) updateVerticalScopeBackground: (id) aParam {
[lockForThread lock];
NSAutoreleasePool *pool = [NSAutoreleasePool new];
//do something
[pool release];
[lockForThread unlockWithCondition:T_FINISHED];
}
-(void) sumFunc {
lockForThread = [[NSConditionLock alloc]
initWithCondition: T_START];
NSThread* updateVerticalScope = [[NSThread alloc] initWithTarget:self selector:#selector(updateVerticalScopeBackground:) object:nil];
[updateVerticalScope start];
//do some processing
[lockForThread lockWhenCondition:T_FINISHED];
[lockForThread unlockWithCondition:T_FINISHED];
[lockForThread release];
}
You could use NSCondition signal/wait.
Could you use a lock to do this? In other words something like this (pseudocode)
create an object to lock on, visible to both threads
dispatch thread A; thread A immediately takes the lock and keeps it for its duration
process something on main thread
main thread attempts to take the lock (this will block until Thread A releases it)
after acquiring the lock, main thread releases it and continues on
You never want your main thread to be blocked waiting for another thread. At least you don't in any application with a user interface because, if the main thread is blocked, your application is frozen.
It would be far better for the main thread to start the background thread, do the other stuff it needs to do and then return to the run loop. The background thread would notify the main thread of completion by sending -performSelectorOnMainThread:waitUntilDone:
I have a piece of network code that uses AsyncSocket but moves it to a separate runloop. I'm creating this runloop with the following piece of code:
[NSThread detachNewThreadSelector:#selector(_workerLoop) toTarget:self withObject:nil];
and here's how my _workerLoop looks like (they're both in the same class):
-(void)_workerLoop {
workerLoop = [[NSRunLoop currentRunLoop] retain];
while(keepWorkerLoopRunning) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[workerLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.5f]];
[pool release];
}
[workerLoop release];
workerLoop = nil;
}
Now, according to the docs, the NSThread will retain the target, and as this thread will only terminate when AsyncSocket disconnects, it's impossible to release and deallocate this object until the socket disconnects.
How can I fix this or maybe I'm doing something wrong?
I've solved this by refactoring the runloop constructor out into own class, referenced by parent class that handles the networking code. This way, parent object is being deallocated, it can stop the thread and release the runloop
I'm working on a small app written in objective-c with the help of the cocoa framework and I am having a multithreading issue.
I would really appreciate it if somebody could help me with some guidance on how terminate a secondary(worker) thread from the main thread?
- (IBAction)startWorking:(id)sender {
[NSThread detachNewThreadSelector:#selector(threadMain:) toTarget:self withObject:nil];
}
- (void)threadMain
{
// do a lot of boring, time consuming I/O here..
}
- (IBAction)stop:(id)sender {
// what now?
}
I've found something on apple's docs but what is missing from this example is the part where the runloop input source changes the exitNow value.
Also, I won't be using many threads in my app so I would prefer a simple solution (with less overhead) rather than a more complex one that is able to manage many threads easily, but with more overhead generated (eg. using locks maybe(?) instead of runloops)
Thanks in advance
I think the easiest way is to use NSThread's -(void)cancel method. You'll need a reference to the thread you've created, as well. Your example code would look something like this, if you can do the worker thread as a loop:
- (IBAction)startWorking:(id)sender {
myThread = [[NSThread alloc] initWithTarget:self selector:#selector(threadMain:) object:nil];
[myThread start];
}
- (void)threadMain
{
while(1)
{
// do IO here
if([[NSThread currentThread] isCancelled])
break;
}
}
- (IBAction)stop:(id)sender {
[myThread cancel];
[myThread release];
myThread = nil;
}
Of course, this will only cancel the thread between loop iterations. So, if you're doing some long blocking computation, you'll have to find a way to break it up into pieces so you can check isCancelled periodically.
Also take a look at the NSOperation and NSOperationQueue classes. It's another set of threading classes that make developing a worker thread model very easy to do.