2010-10-15 21 views
13

Tôi cần đảm bảo rằng cùng một chuỗi sẽ thực hiện các hành động khác nhau vào các thời điểm tùy ý. Đầu tiên thread cần khởi tạo một thư viện, sau đó tôi muốn thread ngủ cho đến khi công việc cần được thực hiện và khi người dùng nhập vào, tôi cần để có thể vượt qua các bộ chọn hoặc các khối để thực thi.Cách gửi bộ chọn hoặc khối tới NSRunLoop để thực hiện?

Làm cách nào để thiết lập NSRunLoop để ngủ sau khi khởi tạo? Sau đó, làm cách nào để báo hiệu vòng lặp chạy để thức dậy và làm điều gì đó?

Tôi đã thử đọc Programming Guide Threading cho iOS, nhưng tôi muốn tránh thiết lập các lớp học như các lớp đầu vào tùy chỉnh và sử dụng một cái gì đó nhẹ hơn như performSelector:onThread:

Tôi có thể thiết lập một bộ đếm thời gian để bắn vĩnh viễn từ bây giờ để vòng lặp chạy không kết thúc?

Dưới đây là về cơ bản những gì tôi muốn trong pseudo-code:

// Initialization Code... 

do { 
    sleepUntilSignaled(); 
    doWorkSentToThisThread(); 
while (!done); 

Nơi tôi gửi công việc để làm dưới dạng tin nhắn performSelector:onThread:. Nó sẽ tốt hơn nếu tôi có thể gửi vòng lặp chạy một khối như: ^{[someObj message]; [otherObj otherMsg];} nhưng tôi muốn được hạnh phúc với performSelector vì tôi khá chắc chắn đó là có thể mà không cần thêm mã hóa thêm.

Cảm ơn!

Trả lời

8

Bạn có tất cả các phần cần thiết cùng nhau trong câu hỏi của mình. Bạn bắt đầu chủ đề của mình và chạy nó là runloop. Nếu bạn cần các chủ đề để làm một cái gì đó bạn có thể sử dụng performSelector:onThread: trên thread chính để làm điều đó.

Có một điều với runloop bạn phải nhận thức được mặc dù: Nó sẽ không chạy trừ khi nó có nguồn đầu vào hoặc bộ hẹn giờ gắn liền với nó. Chỉ cần đính kèm bộ hẹn giờ vào vòng lặp chạy sẽ kích hoạt thời gian trong tương lai xa và bạn đã sẵn sàng.

// Initialization code here 

[NSTimer scheduledTimerWithTimeInterval: FLT_MAX 
           target: self selector: @selector(doNothing:) 
           userInfo: nil repeats:YES]; 

NSRunLoop *rl = [NSRunLoop currentRunLoop]; 
do { 
    [rl runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
} while (!done); 

Sử dụng performSelector:onThread:withObject: bạn cũng có thể chuyển khối của mình tới chuỗi nền. Tất cả những gì bạn cần làm là viết một phương thức ở đâu đó lấy một khối làm tham số và chạy nó:

@interface NSThread (sendBlockToBackground) 
- (void) performBlock: (void (^)())block; 
@end 

@implementation NSThread (sendBlockToBackground) 
- (void) performBlock: (void (^)())block; 
{ 
    [self performSelector: @selector(runBlock:) 
       onThread: self withObject: block waitUntilDone: NO]; 
} 

- (void) runBlock: (void (^)())block; 
{ 
    block(); 
} 
@end 

Nhưng có lẽ bạn nên sử dụng hàng đợi công văn thay vì tất cả điều này. Điều này đòi hỏi mã ít hơn và có lẽ còn ít overhead thêm:

dispatch_queue_t myQueue = dispatch_queue_create("net.example.product.queue", NULL); 
dispatch_async(myQueue, ^{ 
    // Initialization code here 
}); 

// Submit block: 
dispatch_async(myQueue, ^{ 
    [someObject someMethod: someParameter]; 
}); 

Một hàng đợi công văn tạo ra sử dụng dispatch_queue_create là một hàng đợi nối tiếp - tất cả các khối gửi đến nó sẽ được thực hiện theo thứ tự họ đến, cái khác.

+0

Cảm ơn các mẫu mã! Ban đầu tôi đã sử dụng một hàng đợi công văn nhưng nó không tái sử dụng cùng một luồng nếu có quá nhiều thời gian giữa các công văn. –

+0

Có, điều này đúng. Nhưng nó không thực sự quan trọng, trừ khi mã thư viện của bạn phụ thuộc vào chuỗi nó đang chạy.Điều này thường không phải là trường hợp. Ngay cả khi thư viện của bạn cho biết rằng thư viện không an toàn với chủ đề thì cũng không thành vấn đề, miễn là nó không được gọi từ nhiều hơn một luồng * cùng một lúc *. Và điều này sẽ không bao giờ xảy ra với một hàng đợi nối tiếp. – Sven

+1

Thư viện tôi đang sử dụng là PJSUA và khi nó không xác nhận nếu nó phát hiện thấy một chuỗi gọi khác với chuỗi khởi tạo: ( –

0

Tôi nghĩ bạn có thể sử dụng NSInvocationOperation với NSOperationQueue.

+1

Hàng đợi hoạt động không sử dụng lại cùng một chuỗi nếu thời gian giữa các lần gọi quá dài. Nhờ đề nghị mặc dù. –

2

Cân nhắc sử dụng NSConditionLock. Nó được thiết kế cho các nhiệm vụ như thế này. Hãy tưởng tượng rằng bạn có hàng đợi với dữ liệu. Chủ đề đầu tiên thêm dữ liệu vào hàng đợi, luồng thứ hai chờ dữ liệu và xử lý nó.

id condLock = [[NSConditionLock alloc] initWithCondition:NO_DATA]; 

//First thread 
while(true) 
{ 
    [condLock lock]; 
    /* Add data to the queue. */ 
    [condLock unlockWithCondition:HAS_DATA]; 
} 

//Second thread 
while (true) 
{ 
    [condLock lockWhenCondition:HAS_DATA]; 
    /* Remove data from the queue. */ 
    [condLock unlockWithCondition:(isEmpty ? NO_DATA : HAS_DATA)]; 

    // Process the data locally. 
} 
Các vấn đề liên quan