Gypsa
Gypsa

Reputation: 11314

Multiple NSThreads running simultaneously causing app freezes

I am developing an application in which I have a display a lot of images in my table view.These images has to come from server, so I have create another thread in which the image get processed and then set on table view cell to make our table view scrolls smoothly and properly. My problem is when I scrolls my table view to a number of times, the app get freezes and after some time the xcode shows the message shown in below image:- enter image description here

  My table view cell code :-

    id object = [imageDictFunctionApp objectForKey:[NSString stringWithFormat:@"%d",functionAppButton.tag]];
                    if(!object){    

                        NSArray *catdictObject=[NSArray arrayWithObjects:[NSNumber numberWithInt:functionAppButton.tag],indexPath,[NSNumber numberWithInt:i],nil];
                        NSArray *catdictKey=[NSArray arrayWithObjects:@"btn",@"indexPath",@"no",nil];
                        NSDictionary *catPassdict=[NSDictionary dictionaryWithObjects:catdictObject forKeys:catdictKey];
                        [NSThread detachNewThreadSelector:@selector(displayingSmallImageForFunctionsApps:) toTarget:self withObject:catPassdict]; 

                    }
                    else
                    {
                        if(![object isKindOfClass:[NSNull class]]){
                            UIImage *img = (UIImage *)object;
                            [functionAppButton setImage:img forState:UIControlStateNormal];
                        }


-(void)displayingSmallImageForFunctionsApps:(NSDictionary *)dict
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSIndexPath *path=[dict objectForKey:@"indexPath"];
    NSArray *catArray=[self.functionDataDictionary objectForKey:[self.functionsKeysArray objectAtIndex:path.row]];
    int vlaue=[[dict objectForKey:@"no"] intValue];
    NSDictionary *dict1=[catArray objectAtIndex:vlaue];
    NSString *urlString=[dict1 objectForKey:@"artwork_url_large"];
    NSURL *url = [NSURL URLWithString:urlString];
    UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:url]];

    if(image){
        [imageDictFunctionApp setObject:image forKey:[NSString stringWithFormat:@"%d",[[dict objectForKey:@"btn"] intValue]]];
        NSMutableDictionary *dict2=[NSMutableDictionary dictionaryWithCapacity:4];
        [dict2 setObject:image forKey:@"imageValue"];
        [dict2 setObject:[dict objectForKey:@"btn"] forKey:@"tag"];
        [dict2 setObject:[dict objectForKey:@"indexPath"] forKey:@"indexPath"];
        [self performSelectorOnMainThread:@selector(setImageInCellDictCategroryTable:) withObject:dict2  waitUntilDone:NO];


    }
    else{
        [imageDictFunctionApp setObject:[NSNull null] forKey:[NSString stringWithFormat:@"%d",[[dict objectForKey:@"btn"] intValue]]];
    }

    [pool drain];

}

- (void)setImageInCellDictCategroryTable:(NSDictionary *)dict{
    UITableViewCell *myCell = (UITableViewCell *)[categoriesAndFunctionsTableView cellForRowAtIndexPath:[dict objectForKey:@"indexPath"]];
    UIButton *myBtn = (CustomUIButton *)[myCell viewWithTag:[[dict objectForKey:@"tag"] intValue]];
    if ([dict objectForKey:@"imageValue"]) {
        [myBtn setImage:[dict objectForKey:@"imageValue"] forState:UIControlStateNormal];
    }   
}

I have posted all my code that might be linked with this error.Please anyone suggest me how to solve this issue.

Thanks in advance!

Upvotes: 0

Views: 387

Answers (2)

JeremyP
JeremyP

Reputation: 86651

So what I would guess is happening is that you are running out of Mach ports. It looks to me like you are starting a thread for every single cell in your table and then they are all trying to schedule tasks to run on the main runloop when they are done. This is going to stress your system.

I would create an NSOperation for each image and schedule them all on the same NSOperationQueue. The runtime will use a pool of threads tuned to the specific system to run all of the operations.

For a simple thing like this, you can also use GCD as Oscar says, but I recently read on the Apple list that NSOperationQueue is preferred because it is higher level. It gives you more options for controlling what happens to your background tasks.

Upvotes: 1

Oscar Gomez
Oscar Gomez

Reputation: 18488

I would suggest not to use threads and move you code to GCD, looks like what you want to use is a serial queue.

Upvotes: 2

Related Questions