2011-12-21 19 views
14

Tôi có đối tượng NSRunLoop, mà tôi đính kèm bộ tính giờ và luồng. Nó hoạt động tuyệt vời. Ngừng nó là một câu chuyện khác alltogether.CFRunLoopRun() vs [NSRunLoop chạy]

Tôi chạy vòng lặp bằng cách sử dụng [runLoop run].

Nếu tôi cố dừng vòng lặp bằng cách sử dụng CRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]), vòng lặp sẽ không dừng. Nếu tôi bắt đầu vòng lặp bằng cách sử dụng CRunLoopRun() thay vào đó, nó hoạt động. Tôi cũng đã chắc chắn rằng các cuộc gọi được thực hiện trên các chủ đề chính xác (một chạy chạy vòng lặp tùy chỉnh của tôi). Tôi đã sửa lỗi này với pthread_self().

Tôi đã tìm thấy kho lưu trữ danh sách gửi thư, nơi nhà phát triển cho biết "đừng bận tâm sử dụng CRunLoopStop() nếu bạn bắt đầu vòng lặp bằng phương pháp chạy của NSRunLoop". Tôi có thể hiểu tại sao nó là cách nó là - bạn thường ghép đôi initializers và finalizers từ cùng một tập hợp các chức năng.

Làm thế nào để bạn dừng một số NSRunLoop mà không "sử dụng CF"? Tôi không thấy phương thức stop trên NSRunLoop. Các tài liệu nói rằng bạn có thể ngăn chặn một vòng lặp chạy theo ba cách:

  1. Cấu hình chạy vòng lặp để chạy với một giá trị thời gian chờ
  2. Cho vòng lặp chạy để ngừng sử dụng CFRunLoopStop()
  3. Hủy bỏ tất cả các nguồn đầu vào, nhưng đây là một cách không đáng tin cậy để ngăn chặn vòng lặp chạy vì bạn không bao giờ có thể biết những gì bị mắc kẹt những gì vào vòng lặp chạy sau lưng của bạn

Vâng, tôi đã thử 2. và có một "xấu xí" cảm thấy nó, bởi vì bạn phải đào sâu vào CF. 3. là ra khỏi câu hỏi - Tôi không ưa thích mã không xác định.

Điều này để lại cho chúng tôi 1. Nếu tôi hiểu tài liệu chính xác, bạn không thể "thêm" thời gian chờ vào vòng lặp chạy đã tồn tại. Bạn chỉ có thể chạy các vòng chạy mới với thời gian chờ. Nếu tôi chạy một vòng lặp chạy mới, nó sẽ không giải quyết được vấn đề của tôi, vì nó sẽ chỉ tạo ra một vòng lặp chạy lồng nhau. Tôi vẫn sẽ bật lại ngay vào cái cũ, tôi cũng muốn dừng lại ... đúng không? Tôi có thể đã hiểu lầm điều này. Ngoài ra, tôi không muốn chạy vòng lặp với một giá trị thời gian chờ. Nếu tôi làm thế, tôi sẽ phải thực hiện giao dịch giữa các chu kỳ CPU đang cháy (giá trị hết thời gian chờ thấp) và đáp ứng (giá trị thời gian chờ cao).

Đây là thiết lập tôi có ngay bây giờ (pseudo code-ish):

Communicator.h

@interface Communicator : NSObject { 
    NSThread* commThread; 
} 

-(void) start; 
-(void) stop; 
@end 

Communicator.m

@interface Communicator (private) 
-(void) threadLoop:(id) argument; 
-(void) stopThread; 
@end 

@implementation Communicator 
-(void) start { 
    thread = [[NSThread alloc] initWithTarget:self 
            selector:@selector(threadLoop:) 
             object:nil]; 
    [thread start]; 
} 

-(void) stop { 
    [self performSelector:@selector(stopThread) 
       onThread:thread 
       withObject:self 
      waitUntilDone:NO]; 
    // Code ommitted for waiting for the thread to exit... 
    [thread release]; 
    thread = nil; 
} 
@end 

@implementation Communicator (private) 
-(void) stopThread { 
    CRunLoopStop([[NSRunLoop currentRunLoop] getCFRunLoop]); 
} 

-(void) threadLoop:(id) argument { 
    // Code ommitted for setting up auto release pool 

    NSRunLoop* runLoop = [NSRunLoop currentRunLoop]; 

    // Code omitted for adding input sources to the run loop 

    CFRunLoopRun(); 
    // [runLoop run]; <- not stoppable with 

    // Code omitted for draining auto release pools 

    // Code omitted for signalling that the thread has exited 
} 
@endif 

Tôi gì làm? Nó phổ biến/một mô hình tốt để gây rối với CF? Tôi không biết Quỹ đủ tốt. Là can thiệp vào lớp CF có thể nguy hiểm (đối với tham nhũng bộ nhớ, mâu thuẫn, rò rỉ bộ nhớ)? Có mô hình nào tốt hơn để đạt được những gì tôi đang cố đạt được không?

Trả lời

7

Bạn đang hoạt động tốt. Không có vấn đề gì khi sử dụng CoreFoundation khi bạn không thể đạt được mục tiêu của mình với Foundation. Vì CoreFoundation là C, sẽ dễ gây rối hơn cho việc quản lý bộ nhớ nhưng không có nguy hiểm bên trong khi sử dụng CFRunLoop thay vì NSRunLoop (sometimes it may even be safer: CFRunLoop API an toàn chỉ trong khi NSRunLoop thì không).

Nếu bạn muốn dừng NSRunLoop, bạn có thể chạy nó bằng cách sử dụng runMode:beforeDate:. runMode:beforeDate: trả về ngay sau khi nguồn đầu vào được xử lý, do đó bạn không cần đợi đến khi đạt đến ngày hết giờ.

NSRunLoop *runLoop = [NSRunLoop currentRunLoop]; 
NSDate *date = [NSDate distantFuture]; 
while (!runLoopIsStopped && [runLoop runMode:NSDefaultRunLoopMode beforeDate:date]); 

Sau đó, để dừng vòng chạy, bạn chỉ cần đặt runLoopIsStopped thành YES.

+0

Ah, thông minh! Tôi không thấy rằng 'runMode' chỉ chạy một lần. Có một hình phạt hiệu suất đáng kể phát sinh bằng cách bắt đầu vòng lặp chạy lặp đi lặp lại? –

+0

Không, không có: đó là cách hoạt động '- [NSRunLoop]' và '- [NSRunLoop runUntilDate:]'. –

+1

Chủ đề sẽ không dừng lại nếu bạn chỉ thiết lập runLoopIsStopped thành YES. Bạn cần đặt thành CÓ và thực hiện hành động trên chuỗi của chuỗi đó, nếu không thì [runLoop runMode: NSDefaultRunLoopMode beforeDate: date] sẽ không thoát. Điều này đã cho tôi tuổi để tìm ra. – Pada

Các vấn đề liên quan