IOS - Hướng dẫn về Operation Queues trong lập trình Concurrency
Operations Queues xắp xếp thứ tự task được đưa vào xử lý theo các nguyên tắc mà một trong số đó là task nào phụ thuộc vào sự hoàn tất của task khác sẽ được xử lý sau. Điểm quan trọng là 1 task khi được thêm vào Operation queue sẽ được thực thi ngay và không bị xóa khỏi queue cho đến khi nó hoàn tất (kể cả khi task đó bị hủy).
Thay vì sử dụng lớp NSOperation - thực tế là một lớp cơ sở trừu tượng - Apple đã cung cấp 2 lớp con để dùng trong Operation Queues: NSInvocationOperation và NSBlockOperation. Chúng ta sẽ tìm hiểu cụ thể hơn cách sử dụng lớp NSInvocationOperation qua ví dụ sau:
Download source sau để chạy thử : ThreadTestApp
Đầu tiên chúng ta xem xét phần UI gồm các Label và Button trong file Main.storyboard và file ViewController.h khai báo các properties hay phương thức cho các UI này:
![]() |
| Hình chú thích khai báo của các properties của UILabel hay phương thức của UIButton trong Objective-C |
- (void)viewDidLoad {
[super viewDidLoad];
// create a new NSOperationQueue Instance.
operationQueue = [NSOperationQueue new];
// create a new NSOperationObject using NSInvocationOperation subclass.
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(counterTask) object:nil];
[operationQueue addOperation:operation];
// [operation release];
// the same as story above, just tell here to execute the colorRotatorTak method.
operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(colorRotatorTask) object:nil];
[operationQueue addOperation:operation];
}
- counterTask và colorRotatorTask là các phương thức để setText cho các UILabel:
-(void)counterTask{
// Make a BIG loop and every 100 steps let it update the label1 UILabel with the counter's value.
for (int i=0; i < 2000000; i++) {
if (i % 100 == 0) {
// Notice that we use the performSelectorOnMainThread method here instead of setting the label's value directly.
// We do that to let the main thread to take care of showing the text on the label
// and to avoid display problems due to the loop speed.
[_label1 performSelectorOnMainThread:@selector(setText:)
withObject:[NSString stringWithFormat:@"%d", i]
waitUntilDone:YES];
// [NSThread sleepForTimeInterval:0.4];
}
}
// When the loop gets finished then just display a message.
[_label1 performSelectorOnMainThread:@selector(setText:) withObject:@"Thread #1 has finished." waitUntilDone:NO];
}
-(void)colorRotatorTask{
// We need a custom color to work with.
UIColor *customColor;
// Run a loop with 500 iterations.
for (int i=0; i < 500; i++) {
// Create three float random numbers with values from 0.0 to 1.0.
float redColorValue = (arc4random() % 100) * 1.0 / 100;
float greenColorValue = (arc4random() % 100) * 1.0 / 100;
float blueColorValue = (arc4random() % 100) * 1.0 / 100;
// Create our custom color. Keep the alpha value to 1.0.
customColor = [UIColor colorWithRed:redColorValue green:greenColorValue blue:blueColorValue alpha:1.0];
[_label1 performSelectorOnMainThread:@selector(setText:) withObject:[NSString stringWithFormat:@"Thread #2 with number %d has just finished.", i] waitUntilDone:NO];
NSLog(@"%@", [_label1 text]);
// Change the label2 UILabel's background color.
[_label2 performSelectorOnMainThread:@selector(setBackgroundColor:) withObject:customColor waitUntilDone:YES];
// Set the r, g, b and iteration number values on label3.
[_label3 performSelectorOnMainThread:@selector(setText:)
withObject:[NSString stringWithFormat:@"Red: %.2f\nGreen: %.2f\nBlue: %.2f\nIteration #: %d", redColorValue, greenColorValue, blueColorValue, i]
waitUntilDone:YES];
// Put the thread to sleep for a while to let us see the color rotation easily.
[NSThread sleepForTimeInterval:0.4];
}
// Show a message when the loop is over.
[_label3 performSelectorOnMainThread:@selector(setText:) withObject:@"Thread #2 has finished." waitUntilDone:NO];
}
Các task sẽ được chạy theo 2 thread đồng thời và xen vào nhau mà ta sẽ thấy khi chạy app. Ngoài ra còn 1 thread cũng khác chạy đồng thời qua các phương thức bắt touch event của 1 trong các UIButton Color #1, Color #2, Color #3:
- (IBAction)applyBackgroundColor1:(id)sender {
[self.view setBackgroundColor:[UIColor colorWithRed:255.0/255.0 green:204.0/255.0 blue:102.0/255.0 alpha:1.0]];
}
- (IBAction)applyBackgroundColor2:(id)sender {
[self.view setBackgroundColor:[UIColor colorWithRed:204.0/255.0 green:255.0/255.0 blue:102.0/255.0 alpha:1.0]];
}
- (IBAction)applyBackgroundColor3:(id)sender {
[self.view setBackgroundColor:[UIColor whiteColor]];
}
Khi chạy ứng dụng, ta sẽ nhận ra thread của counterTask và colorRotatorTask chạy đồng thời xen cài với nhau (trên trong Label 1 đôi lúc xuất hiện dòng chữ 'Thread #2 with number ... has just finished.' thay vì xuất hiện những số nguyên dương). Ví dụ này cho chúng ta thấy rõ cơ chế chạy Concurrency của các thread trong NSOperationQueue.

Không có nhận xét nào :
Đăng nhận xét