多线程的使用与注意事项
多线程的使用与注意事项
这一回,主要介绍一下iPhone SDK中多线程的使用方法以及注意事项。虽然现在大部分PC应用程序都支持多线程/多任务的开发方式,但是在iPhone上,Apple并不推荐使用多线程的编程方式。但是多线程编程毕竟是发展的趋势,而且据说即将推出的iPhone OS4将全面支持多线程的处理方式。所以说掌握多线程的编程方式,在某些场合一定能挖掘出iPhone的更大潜力。
从例子入手
先从一个例程入手,具体的代码参考了这里。还有例程可以下载。
多线程程序的控制模型可以参考这里,一般情况下都是使用 管理者/工人模型, 这里,我们使用iPhone SDK中的 NSThread 来实现它。
首先创建一个新的 View-based application 工程,名字为 "TutorialProject" 。界面如下图所示,使用UILabel实现两部分的Part(Thread Part和Test Part),Thread Part中包含一个UIProgressView和一个UIButton;而Test Part包含一个值和一个UISlider。
接下来,在 TutorialProjectViewController.h 文件中创建各个UI控件的 IBOutlets.
@interface TutorialProjectViewController : UIViewController { // ------ Tutorial code starts here ------ // Thread part IBOutlet UILabel *threadValueLabel; IBOutlet UIProgressView *threadProgressView; IBOutlet UIButton *threadStartButton; // Test part IBOutlet UILabel *testValueLabel; // ------ Tutorial code ends here ------}
@property (nonatomic, retain) IBOutlet UILabel *threadValueLabel;@property (nonatomic, retain) IBOutlet UIProgressView *threadProgressView;@property (nonatomic, retain) IBOutlet UIProgressView *threadStartButton;@property (nonatomic, retain) IBOutlet UILabel *testValueLabel;
- (IBAction) startThreadButtonPressed:(UIButton *)sender;- (IBAction) testValueSliderChanged:(UISlider *)sender;
@synthesize threadValueLabel, threadProgressView, testValueLabel, threadStartButton;...- (void)dealloc { // ------ Tutorial code starts here ------ [threadValueLabel release]; [threadProgressView release]; [threadStartButton release]; [testValueLabel release]; // ------ Tutorial code ends here ------ [super dealloc];}
- (IBAction) startThreadButtonPressed:(UIButton *)sender { threadStartButton.hidden = YES; threadValueLabel.text = @"0"; threadProgressView.progress = 0.0; [NSThread detachNewThreadSelector:@selector(startTheBackgroundJob) toTarget:self withObject:nil];}
- (void)startTheBackgroundJob { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; // 线程开始后先暂停3秒(这里只是演示暂停的方法,你不是必须这么做的) [NSThread sleepForTimeInterval:3]; [self performSelectorOnMainThread:@selector(makeMyProgressBarMoving) withObject:nil waitUntilDone:NO]; [pool release];}
- (void)makeMyProgressBarMoving { float actual = [threadProgressView progress]; threadValueLabel.text = [NSString stringWithFormat:@"%.2f", actual]; if (actual < 1) { threadProgressView.progress = actual + 0.01; [NSTimer scheduledTimerWithTimeInterval:0.5 target:self selector:@selector(makeMyProgressBarMoving) userInfo:nil repeats:NO]; } else threadStartButton.hidden = NO;}
- (IBAction) testValueSliderChanged:(UISlider *)sender { testValueLabel.text = [NSString stringWithFormat:@"%.2f", sender.value];}
#include "pthread.h"void *threadFunc(void *arg) { void* stack_base = pthread_get_stackaddr_np(pthread_self()); size_t stack_size = pthread_get_stacksize_np(pthread_self()); NSLog(@"Thread: base:%p / size:%u", stack_base, stack_size); return NULL;}- (void)applicationDidFinishLaunching:(UIApplication *)application { void* stack_base = pthread_get_stackaddr_np(pthread_self()); size_t stack_size = pthread_get_stacksize_np(pthread_self()); struct rlimit limit; getrlimit(RLIMIT_STACK, &limit); NSLog(@"Main thread: base:%p / size:%u", stack_base, stack_size); NSLog(@" rlimit-> soft:%llu / hard:%llu", limit.rlim_cur, limit.rlim_max); pthread_t thread; pthread_create(&thread, NULL, threadFunc, NULL); // Override point for customization after app launch [window addSubview:viewController.view]; [window makeKeyAndVisible];}
NSAutoReleaseNoPool(): Object 0x********* of class NSConreteData autoreleased with no pool in place ….
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
imageView.image = [UIImage imageNamed:@"Hoge.png"];
[delegate performSelectorOnMainThread:@selector(theProcess:) withObject:nil waitUntilDone:YES];