views:

79

answers:

1

I have an iphone app where on the loading of a view controller, I want to call a web service , get and parse XML all on the background thread. Then update the ui after the thread is done, then fire off another thread to do a secondard operation in another background thread.

Sort of like chaining threading calls:

  1. UI Thread -> Create BG Thread
  2. BG Thread -> Call XML service and get results
  3. UI Thread -> Update UI of the success of the BG Thread operation
  4. BG Thread -> Fire off part 2 of the operation

All on load of the app.

The issue is that my first, BG Thread operation never seems to end. I added in a waitUntilAllOperationsAreFinished call after step 2 is done, just to see whats going on and my app never seems to get past that point.

This is sort of the basic skeleton implementation:

- (void) viewDidLoad 
{
    queue = [[NSOperationQueue alloc] init];
[queue setMaxConcurrentOperationCount:1];

    //other stuff

    [self loadFriendsInBackgroundThread];
}

- (void) loadFriendsInBackgroundThread
{   
    NSInvocationOperation *operation = [NSInvocationOperation alloc];
    operation = [operation initWithTarget:self selector:@selector(invokeLoadingOfFriends:) object: nil];

    [queue addOperation:operation];
[operation release];
}

- (void) invokeLoadingOfFriends: (id) obj
{
    //webservice calls and results

    [self performSelectorOnMainThread:@selector(invokeRefreshAfterLoadingFriends:) 
                       withObject:nil 
                    waitUntilDone:YES];
}

- (void) invokeRefreshAfterLoadingFriends: (id) obj
{
    //this line is where is hangs
    [queue waitUntilAllOperationsAreFinished];

    //never gets here
    [self refresh: NO];
}

Any ideas as to why the first thread call never seems to end?

Thanks for any help you can give Mark

+2  A: 

Here, you are calling a method on the main thread that waits until the called method is done (waitUntilDone:YES):

[self performSelectorOnMainThread:@selector(invokeRefreshAfterLoadingFriends:) 
                   withObject:nil 
                waitUntilDone:YES];

You then call -invokeRefreshAfterLoadingFriends: which holds up the main thread until the operation finishes, so the method never gets "done". From the documentation for -waitUntilAllOperationsAreFinished:

When called, this method blocks the current thread and waits for the receiver’s current and queued operations to finish executing.

As a result, the -invokeLoadingOfFriends: operation method sits waiting for the main thread's method to finish, which never happens because you held up the main thread with [queue waitUntilAllOperationsAreFinished].

Try setting waitUntilDone to NO and see if this helps the operation finish.

Alex Reynolds
Oh man, thanks, cant believe i missed that one, for some reason I assumed that the waitUntilDone parameter did something different :) Thanks
Mark