3

I'm trying to make a test app which measures the performance for threads. However, I'm trying to set an image to imageview on a thread and it's not updating. In fact, the methods setImage1 and setImage2 aren't even getting called. Any ideas? Look at the code for details

#import "UntitledAppDelegate.h"
#import <QuartzCore/QuartzCore.h>

@implementation UntitledAppDelegate

@synthesize window, imageView1, imageView2, label1, label2, label0;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{            
    [window makeKeyAndVisible];
    return YES;
}

-(IBAction) startSeparate:(id) sender
{
 imageView1.image = imageView2.image = nil;
 double prev;

    start = prev = CACurrentMediaTime(); 
 [self setImage1];
 label1.text = [NSString stringWithFormat:@"%.10g", CACurrentMediaTime() - prev];

 prev = CACurrentMediaTime();  
 [self setImage2];
 label2.text = [NSString stringWithFormat:@"%.10g", CACurrentMediaTime() - prev];
}

-(IBAction) startThreaded:(id) sender
{
 imageView1.image = imageView2.image = nil;
 double prev;

 NSThread *t1 = [[NSThread alloc] init];
 [t1 start];
 NSThread *t2 = [[NSThread alloc] init];
 [t2 start];

    start = prev = CACurrentMediaTime(); 
    //This doesn't work
    //[self performSelector:@selector(setImage1) onThread:t1 withObject:nil waitUntilDone:NO];

    //But this does
 [self performSelectorInBackground:@selector(setImage1) withObject:nil];

 label1.text = [NSString stringWithFormat:@"%.10g", CACurrentMediaTime() - prev];

 prev = CACurrentMediaTime();  
 //This doesn't work
    //[self performSelector:@selector(setImage2) onThread:t2 withObject:nil waitUntilDone:NO];

    //But this does
 [self performSelectorInBackground:@selector(setImage2) withObject:nil];

 label2.text = [NSString stringWithFormat:@"%.10g", CACurrentMediaTime() - prev];
}

-(void) setImage1
{
 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 UIImage *image1 = [UIImage imageNamed:@"bird.png"];
 imageView1.image = image1;
 [self pictureDone];
 [pool drain];
}

-(void) setImage2
{
 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 UIImage *image2 = [UIImage imageNamed:@"bird.png"];
 imageView2.image = image2;
 [self pictureDone];
 [pool drain];
}

-(void) pictureDone
{
 done++;
 NSLog(@"%i", done);
 if (done == 2) {
  label0.text = [NSString stringWithFormat:@"%.10g", CACurrentMediaTime() - start];
  done = 0;
 }
}
@end
tadejsv
  • 2,085
  • 1
  • 18
  • 20

2 Answers2

5

Never change anything in a currently displayed UIView from a background thread. There are a million different synchronization problems that you can encounter. Download the image in the background thread, and then call another method on the main thread (from the background thread) to actually update the UIImageView

performSelectorOnMainThread:...

As for the problem with the method not running, try this instead:

[self performSelectorInBackground:@selector(setImage2:) withObject:nil];

(adding a colon after setImage2).

Also, I don't think those two NSThread objects (t1 and t2) are necessary, and they are also probably creating a memory leak.

jmans
  • 5,648
  • 4
  • 27
  • 32
3

Technically, NSThread itself do not create run loop automatically, then the performSelector:onThread won't work if you just create thread that way.

tia
  • 9,518
  • 1
  • 30
  • 44
  • I just found out that this was in fact the problem. I guess I'll have to take my time and read the thread programming guide ;) – tadejsv Nov 05 '10 at 21:37
  • I'm not sure what your project is about, but in many scenarios using `performSelectorInBackground` is enough. – tia Nov 05 '10 at 21:46