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  阅读(8900)  评论(0编辑  收藏  举报

导航