2013-05-10 18 views
5

Tôi đã đọc nhiều bài đăng về NSRunLoop, như this, this, this. Nhưng không thể tìm ra những gì thực sự làm NSRunLoopNSRunLoop làm gì?

Những gì tôi thường thấy là một sợi công nhân

wthread = [[NSThread alloc] initWithTarget:self selector:@selector(threadProc) object:nil]; 
[wthread start]; 

với một NSRunLoop bên trong nó

- (void)threadProc 
{ 
    NSAutoreleasePool* pool1 = [[NSAutoreleasePool alloc] init]; 
    BOOL isStopped = NO; 
    NSRunLoop *runloop = [NSRunLoop currentRunLoop]; 
    [runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; 

    while (!isStopped) 
    { 
     { 
      NSAutoreleasePool* pool2 = [[NSAutoreleasePool alloc] init]; 
      [runloop runMode:NSDefaultRunLoopMode 
             beforeDate:[NSDate distantFuture]]; 

      [pool2 release]; 
     } 
    } 

    [pool1 release]; 
} 

Và các chủ đề chính đi một số công việc này wthread

[self performSelector:@selector(someWork:) onThread:wthread withObject:nil waitUntilDone:NO]; 

Trong thời gian chuyển công việc từ chuỗi chính đến wor chủ đề ker, tôi thấy nhiều người làm điều này. Tại sao cần NSRunLoop ở đây? Nó làm gì ?

Tôi đọc rằng NSRunLoop được sử dụng để quản lý sự kiện, tại sao không có gì ngoại trừ việc gọi runMode bên trong threadProc?

+0

tôi nghĩ về nó như một fancy while (true) {// chèn công việc được thực hiện ở đây}, trong đó bạn có thể tự động thêm mã để thực hiện (sự kiện, công việc, ổ cắm, v.v.). Các runloop không thực sự trống rỗng, một cổng đã được gắn liền với runloop, nó là một hình thức truyền thông interprocess. – foFox

+0

Tôi thấy http://bou.io/RunRunLoopRun.html là hữu ích cũng như – onmyway133

Trả lời

3

Ví dụ bạn đã hiển thị là thành ngữ Cocoa để tạo chuỗi sẽ tiếp tục chạy sau khi thoát khỏi phương pháp -threadProc. Tại sao?

Bởi vì:

  • các NSRunLoop dụ bạn đã tạo đã ít nhất một nguồn đầu vào ([NSMachPort port])
  • bạn đã bắt đầu một cách rõ ràng vòng lặp chạy với runMode:beforeDate

Nếu không có thêm một nguồn đầu vào và bắt đầu một cách rõ ràng vòng lặp chạy, luồng sẽ kết thúc.

Parenthetically, mặc dù chạy vòng vẫn còn quan trọng để quản lý sự kiện và một số nhiệm vụ không đồng bộ, tôi sẽ không xem NSThread làm cách mặc định kiến ​​trúc công việc không đồng bộ nhất trong ứng dụng Cocoa hiện nay. GCD là một cách gọn gàng hơn để đóng gói công việc nền.

EDIT:

Nộp việc phải xếp hàng nối tiếp trong GCD:

@interface Foo : NSObject 
@end 

@implementation Foo { 
    dispatch_queue_t _someWorkerQueue; 
} 

- (id)init { 
    self = [super init]; 
    if(!self) return nil; 

    _someWorkerQueue = dispatch_queue_create("com.company.MyWorkerQueue", 0); 
    return self; 
} 

- (void)performJob { 
    dispatch_async(_someWorkerQueue, ^{ 
     //do some work asynchronously here 
    }); 

    dispatch_async(_someWorkerQueue, ^{ 
     //more asynchronous work here 
    }); 
} 
@end 
+0

1) Vì vậy, tại sao có trong khi vòng lặp bên trong threadProc? 2) GCD sẽ chuyển giao công việc cho bất kỳ chủ đề có sẵn/chưa biết nào, nhưng NSRunLoop sẽ đảm bảo tất cả công việc sẽ được chuyển đến cùng một chuỗi công nhân này, đúng không? – onmyway133

+0

Để cung cấp một cơ chế để chấm dứt vòng lặp chạy - khi cờ 'isStopped' được đặt (mặc dù nó không được hiển thị trong mã ...) – FluffulousChimp

+0

2) xem câu trả lời đã chỉnh sửa cho phương pháp GCD đối với trường hợp sử dụng mà bạn mô tả. – FluffulousChimp

3

Phần lớn xảy ra ở hậu trường. Lý do cho điều này là nó cung cấp một cách để các thread ngừng thực hiện khi không có các mục công việc. Nếu bạn đã từng sử dụng hệ điều hành thời gian thực, các tác vụ cần một nơi để từ bỏ bộ xử lý để người khác có thể chạy.

Điều gì không được ghi lại đầy đủ là khi bạn gửi performSelector: onThread: ..., đó là vòng lặp chạy xếp hàng đợi thư và đánh thức để cho phép luồng xử lý nó. Nếu bạn thêm thông điệp tường trình vào vòng lặp while bạn có thể thấy điều này xảy ra.

Đối với thực sự tò mò có mã mẫu trên github bạn có thể chơi xung quanh với vòng lặp chạy - thêm nhận xét và tôi sẽ liệt kê một vài.

+0

1) nhưng bên trong chuỗiProc, có một vòng lặp while, do đó, luồng sẽ luôn bận? Làm thế nào NSRunLoop có thể yêu cầu nó ngừng thực hiện? 2) AFAIK, đây là một cơ chế để đảm bảo rằng nhiều cuộc gọi đến performSelector: onThread: sẽ chuyển công việc tới cùng một luồng công nhân này, đúng không? – onmyway133

+0

1) xin lỗi không được rõ ràng - hệ điều hành sẽ đình chỉ các chủ đề bên trong runMode: nếu không có gì cho mã của bạn để xử lý. 2) nó là một tính năng của hệ thống - nhưng có những tính năng khác - xử lý cổng và hẹn giờ. Bạn sẽ học được nhiều nhất bằng cách đọc tài liệu táo trên CFRunloop - Tôi tin rằng có một hướng dẫn về nó. –