Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

walty

macrumors member
Original poster
Jul 15, 2008
33
0
OK, this is really desperate and painful, and I am now stuck and hungry in office :(


Basically, I only need to run some operations on IPhone after the execution of main UI thread. And I used NSOperation and NSOperationQueue for this. I checked the SDK, and here is what I wrote for testing this behaviour:


I got a simple class inherit from NSOperations

TestLoader.h
Code:
#import <UIKit/UIKit.h>


@interface TestLoader : NSOperation {
	bool running,started;
	int threadID;
}

-(id)initWithThreadID:(int)threadID_;

@end

TestLoader.m
Code:
#import "TestLoader.h"


@implementation TestLoader
-(id)initWithThreadID:(int)threadID_
{
	self = [super init];
	running = FALSE;
	started = FALSE;
	threadID = threadID_;
	return self;
}

- (BOOL)isExecuting
{
	return running;
}

- (BOOL)isFinished
{
	return started && !running;
}

- (void)start
{
	running = true;
	started = TRUE;
	
	sleep(3);
	for(int i=0; i<10; i++)
		NSLog(@"@17,inside thread %d ", threadID);
	
	running = false;
	
}

- (BOOL)isConcurrent
{
	return YES;
}

and then in my appDelegate.m, I put this into applicationDidFinishLaunching

Code:
//queue is of NSOperationQueue object and is instantiated in init:

	[queue setMaxConcurrentOperationCount:2];
	TestLoader *loader = [[TestLoader alloc]initWithThreadID:1];
	[queue addOperation:loader];
	NSLog(@"@53,add new thread");
	[queue addOperation:[[TestLoader alloc]initWithThreadID:2]];
	[loader release];
	NSLog(@"@37, about to quite main thread");


and this is the output:

Code:
2008-09-29 20:03:04.273 Rosetta[13090:20b] @17,inside thread 1 
2008-09-29 20:03:04.275 Rosetta[13090:20b] @17,inside thread 1 
2008-09-29 20:03:04.278 Rosetta[13090:20b] @17,inside thread 1 
2008-09-29 20:03:04.278 Rosetta[13090:20b] @17,inside thread 1 
2008-09-29 20:03:04.279 Rosetta[13090:20b] @17,inside thread 1 
2008-09-29 20:03:04.279 Rosetta[13090:20b] @17,inside thread 1 
2008-09-29 20:03:04.280 Rosetta[13090:20b] @17,inside thread 1 
2008-09-29 20:03:04.280 Rosetta[13090:20b] @17,inside thread 1 
2008-09-29 20:03:04.281 Rosetta[13090:20b] @17,inside thread 1 
2008-09-29 20:03:04.281 Rosetta[13090:20b] @17,inside thread 1 
2008-09-29 20:03:04.282 Rosetta[13090:20b] @53,add new thread
2008-09-29 20:03:07.282 Rosetta[13090:20b] @17,inside thread 2 
2008-09-29 20:03:07.284 Rosetta[13090:20b] @17,inside thread 2 
2008-09-29 20:03:07.284 Rosetta[13090:20b] @17,inside thread 2 
2008-09-29 20:03:07.285 Rosetta[13090:20b] @17,inside thread 2 
2008-09-29 20:03:07.286 Rosetta[13090:20b] @17,inside thread 2 
2008-09-29 20:03:07.287 Rosetta[13090:20b] @17,inside thread 2 
2008-09-29 20:03:07.287 Rosetta[13090:20b] @17,inside thread 2 
2008-09-29 20:03:07.288 Rosetta[13090:20b] @17,inside thread 2 
2008-09-29 20:03:07.288 Rosetta[13090:20b] @17,inside thread 2 
2008-09-29 20:03:07.289 Rosetta[13090:20b] @17,inside thread 2 
2008-09-29 20:03:07.289 Rosetta[13090:20b] @37, about to quite main thread

so, basically:

1. the main thread is blocked until all 2 threads are done
2. the second thread is not added until first thread is done


I googled around for 2 hours, and found some sample code in Cocoa, but none is for iPhone, anyone any hint please?!!!

thanks a lot
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
Did you actually read the documentation?

Quoting from http://developer.apple.com/document...OperationQueue_class/Reference/Reference.html

"If the isConcurrent method of an operation returns NO, the operation queue automatically creates a new thread for that operation before running it. If the isConcurrent method returns YES, the operation object must create its own thread or otherwise configure its own runtime environment as part of its execution phase."

You are returning YES for isConcrrent so it's up to you to start a thread. As you aren't starting a thread each NSOperation will block the calling thread until it is complete which is exactly what we see with your output.
 

walty

macrumors member
Original poster
Jul 15, 2008
33
0
OK, hm... works now, STUPID ME!!!!

Last night, I just focused on checking the documentation of NSOperation, which say that

By default, operations are designated as non-concurrent. For information on how to create a concurrent operation object, see the subclassing notes for this class.


And last night I have tried to manually trigger the NSOperation, and then tried to insert them into NSOperationQueue, actually I have read the mentioned line once, just I am not quite sure what it means when I read it. Actually, I could be more carefully, I should find the following in the heading of NSOperation doucmentation:

There are some situations though where you might want to create a concurrent operation instead, including the following:

You want to create the thread yourself.
You want to launch a separate task instead of a thread.
Your operation’s main method initiates an asynchronous call and exits. (In such a situation, the callback function or method would then pass control to the operation object to process the request. For example, you could use this technique to set up a timer and then use the methods of the operation object to do some work each time the timer fires. )

Which basically, I need to explicitly create the thread myself anyway if I use concurrent operation..

May be next time, when I stuck too long, I should just go home and watch TV..


Finally, REALLY REALLY THANKS A LOT!!!


Did you actually read the documentation?

Quoting from http://developer.apple.com/document...OperationQueue_class/Reference/Reference.html

"If the isConcurrent method of an operation returns NO, the operation queue automatically creates a new thread for that operation before running it. If the isConcurrent method returns YES, the operation object must create its own thread or otherwise configure its own runtime environment as part of its execution phase."

You are returning YES for isConcrrent so it's up to you to start a thread. As you aren't starting a thread each NSOperation will block the calling thread until it is complete which is exactly what we see with your output.
 

robbieduncan

Moderator emeritus
Jul 24, 2002
25,611
893
Harrogate
May be next time, when I stuck too long, I should just go home and watch TV..

This is a really good idea. Sometimes what you need is a break from staring at the same, seemingly correct code. If you go do something else and come back with fresh eyes often times the mistake suddenly becomes clear :)
 

youPhone

macrumors member
Sep 8, 2008
41
0
This post is supposed to help keep people from making the same stupid mistake I just made and fixed.

I started writing a reply where I was getting the behavior:
I used this same example, but added a 3rd operation to the queue and I changed isConcurrent to YES. Only the first two threads were running and the 3rd never did.

After writing the whole reply (and I had been working on the problem for a couple hours -- even reading the docs over), I decided to check the the NSOperation and NSOperationQueue docs one more time.

It turns out, when you're going to concurrent=NO, you ("typically") need to only override the main function and not all of the others (start, isConcurrent, isExecuting, isFinished)........as it says in the documentation. :rolleyes:

After commenting out those functions and moving the logic from "start" to "main", it was all working like it should be.

Another lesson in reading the documentation one last time before posting.

Hope this helps.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.