WWDC2010 Session206 介绍iPhone上的Blocks和Grand Central Dispatch (2)
Grand Central Dispatch
使用GCD,可以让你的程序不会失去响应. 多线程不容易使用,用了GCD,会让它变得简单。你无需专门进行线程管理, 很棒!
让你的程序保持响应的原则:
1. 不要柱塞主线程
2. 把工作一到其他线程中做。
3. 做完后更新主线程的UI.
没有GCD的代码:
- (void)addTweetWithMsg:(NSString*)msg url:(NSURL*)url {
// Controller UI callback on main thread
DTweet *tw = [[DTweet alloc] initWithMsg:msg];
[tweets addTweet:tw display:YES];
tw.img = [imageCache getImgFromURL:url];//bottle neck
[tweets updateTweet:tw display:YES];
[tw release];
}
有GCD的代码:
- (void)addTweetWithMsg:(NSString*)msg url:(NSURL*)url {
// Controller UI callback on main thread
DTweet *tw = [[DTweet alloc] initWithMsg:msg];
[tweets addTweet:tw display:YES];
dispatch_async(image_queue, ^{
tw.img = [imageCache getImgFromURL:url];
dispatch_async(main_queue, ^{
[tweets updateTweet:tw display:YES];
});
});
[tw release];
}
GCD Queues
1. Lightweight list of blocks
2. Enqueue/dequeue is FIFO
3. Enqueue with dispatch_async()
4. Dequeue by automatic thread or main thread
Main Queue
1. Executes blocks one at a time on main thread
2. Cooperates with the UIKit main run loop
3. dispatch_get_main_queue()
Creating your own queues
1. Execute blocks one at a time
2. On automatic helper thread
3. “Queue up” background work
dispatch_queue_t queue;
queue = dispatch_queue_create(“com.example.purpose”, NULL);
dispatch_release(queue);
Queues Instead of Locks
1. Enqueuing is thread-safe.
2. Execution is serial
3. Protect access to shared data
4. Queues are lightweight
Managing Queue Lifetime
1. Queues are reference counted. dispatch_retain() / dispatch_release()
2. GCD retains parameters to dispatch API as necessary
3. Ensure correct queue lifetime across asynchronous operations
4. Ensure objects captured by blocks are valid when blocks are executed
5. Objective-c objects are auto-retained/released
6 Other objects must be retained by your code. CFRetain() / CFRelease()
- (void)asyncParseData:(NSData *)date
queue:(dispatch_queue_t)queue
block:(void (^)(id result))block {
dispatch_retain(queue);
dispatch_async(self.parse_queue, ^{
id result = [self parseData:data];
dispatch_async(queue, ^{
block(result);
});
dispatch_release(queue);
});
}
App Design with Queues
Demo app tasks
1. Receive and parse network stream
2. Maintain message history
3. Fetch and cache images
4. Display user interface
Without GCD
NSData *d = [twitterStream receiveData];
DTweet *tw = [[DTweet alloc] initWithData:d];
[[tweets addTweet:tw];
[viewController displayTweet:tw]; });
tw.img = [imageCache getImgFromURL:tw.url];
[viewController updateTweetDisplay:tw];
[tw release];
With GCD
dispatch_async(network_queue, ^{
NSData *d = [twitterStream receiveData];
DTweet *tw = [[DTweet alloc] initWithData:d];
dispatch_async(tweets_queue, ^{
[[tweets addTweet:tw];
dispatch_async(main_queue, ^{
[viewController displayTweet:tw]; });
});
dispatch_async(image_queue, ^{
tw.img = [imageCache getImgFromURL:tw.url];
dispatch_async(main_queue, ^{
[viewController updateTweetDisplay:tw];
});
});
});
[tw release];
});
Pitfalls
1. Avoid blocking per-subsystem queues
2. Be careful when waiting. (deadlock)
3. Blocked worker threads consume resources
Responding to External Events
Dispatch sources
1. Monitor external events
- Files, Network Sockets, Directories, Timers
2. Event handlers can be delivered to any queue
3. Use sources to replace polling or blocking API calls
4. See session 211:
Simplifying iPhone App Development with Grand Central Dispatch
Where do I find GCD?
1. GCD is part of libSystem.dylib
2. #include <dispatch/dispatch.h>
WWDC2010 Session206 Introducing Blocks and Grand Central Dispatch on iPhone
Author: Kevin van Vechten - Manager, Core OS
posted on 2011-04-07 15:35 VinceOniPhone 阅读(8924) 评论(0) 编辑 收藏 举报