2013-07-31 25 views
10

Làm thế nào để chờ đợi bên trong NSThread cho đến khi một số sự kiện xảy ra trong iOS?Làm thế nào để chờ trong NSThread cho đến khi một số sự kiện xảy ra trong iOS?

ví dụ: Chúng tôi đã tạo NSThread và bắt đầu vòng lặp chuỗi. Bên trong vòng lặp chuỗi, có điều kiện để kiểm tra xem hàng đợi tin nhắn có bất kỳ tin nhắn nào không. Nếu có một tin nhắn, sau đó nó sẽ gọi phương thức tương ứng để thực hiện một số thao tác, nếu không nó sẽ đợi cho đến khi hàng đợi tin nhắn được điền bằng một tin nhắn mới.

Có bất kỳ API hoặc phương thức nào có sẵn để chờ cho đến khi một số sự kiện xảy ra không?

For Example 

NSThread *thread = [NSThread alloc][email protected](threadLoop) 

- (void)threadLoop 
{ 
    // Expecting some API or method that wait until some messages pushed into the message queue 
    if (...) { 

    } 
} 

Mọi trợ giúp cần được đánh giá cao.

Trả lời

13

Bạn có thể sử dụng NSCondition. Tôi đính kèm mã ví dụ "sẵn sàng cho thử nghiệm" trong một ViewController

@interface ViewController() 

@property (strong, nonatomic) NSCondition *condition; 
@property (strong, nonatomic) NSThread *aThread; 

// use this property to indicate that you want to lock _aThread 
@property (nonatomic) BOOL lock; 

@end 

@implementation ViewController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 

    // start with the thread locked, update the boolean var 
    self.lock = YES; 

    // create the NSCondition instance 
    self.condition = [[NSCondition alloc]init]; 

    // create the thread and start 
    self.aThread = [[NSThread alloc] initWithTarget:self selector:@selector(threadLoop) object:nil]; 
    [self.aThread start]; 

} 

-(void)threadLoop 
{ 
    while([[NSThread currentThread] isCancelled] == NO) 
    { 
     [self.condition lock]; 
     while(self.lock) 
     { 
      NSLog(@"Will Wait"); 
      [self.condition wait]; 

      // the "did wait" will be printed only when you have signaled the condition change in the sendNewEvent method 
      NSLog(@"Did Wait"); 
     } 

     // read your event from your event queue 
     ... 


     // lock the condition again 
     self.lock = YES; 
     [self.condition unlock]; 
    } 

} 

- (IBAction)sendNewEvent:(id)sender { 
    [self.condition lock]; 
    // put the event in the queue 
    ... 


    self.lock = NO; 
    [self.condition signal]; 
    [self.condition unlock]; 
} 
+0

Chính xác những gì tôi đang tìm kiếm. Ví dụ đơn giản, sạch sẽ tuyệt vời. –

+0

ví dụ tuyệt vời – ashokdy

2

Bạn có thể sử dụng semaphore. Xem ví dụ dưới đây, logic khá đơn giản. Im ví dụ của tôi, các khối được thực hiện trong nền, và chủ đề chính của tôi chờ đợi cho các tín hiệu công văn của semaphore để đi về. Sự khác biệt chính là trong trường hợp của tôi thread chờ đợi là chủ đề chính, nhưng logic semaphore là ở đây, tôi nghĩ rằng bạn có thể dễ dàng thích nghi điều này với trường hợp của bạn.

//create the semaphore 
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); 

[objectManager.HTTPClient deletePath:[address addressURL] parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { 

     //some code here 

     dispatch_semaphore_signal(semaphore); 

    }failure:^(AFHTTPRequestOperation *operation, NSError *error) { 

     //some other code here 

     dispatch_semaphore_signal(semaphore); 
    }]; 

//holds the thread until the dispatch_semaphore_signal(semaphore); is send 
while (dispatch_semaphore_wait(semaphore, DISPATCH_TIME_NOW)) 
{ 
    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10]]; 
} 
3

Bạn có thể sử dụng run loop sources. Về bản chất:

1) Trên sợi nhân thứ cấp tạo ra và cài đặt nguồn vòng lặp chạy, và vượt qua nó bằng cách nào đó, cùng với nhân viên chủ đề tham khảo chạy vòng lặp, vào chủ đề quản lý khác sẽ được gửi tin nhắn với trang này:

CFRunLoopSourceContext context = {0, self, NULL, NULL, NULL, NULL, NULL, 
            &RunLoopSourceScheduleRoutine, 
            RunLoopSourceCancelRoutine, 
            RunLoopSourcePerformRoutine}; 
    CFRunLoopSourceRef runLoopSource = CFRunLoopSourceCreate(NULL, 0, &context); 
    CFRunLoopRef runLoop = CFRunLoopGetCurrent(); 
    CFRunLoopAddSource(runLoop, runLoopSource, kCFRunLoopDefaultMode); 
    // Pass runLoopSource and runLoop to managing thread 

Ở đây có những thói quen tùy chỉnh nêu trên - bạn có trách nhiệm cung cấp cho họ:

RunLoopSourceScheduleRoutine - called when you install run loop source (more precisely, when you call CFRunLoopAddSource) 

    RunLoopSourceCancelRoutine - called when you remove run loop source (more precisely, when you call CFRunLoopSourceInvalidate) 

    RunLoopSourcePerformRoutine - called when run loop source was signaled (received a message from manager thread) and this is a place where you should perform a job 

2) Mở thread công nhân, bắt đầu vòng chạy bình thường, một cái gì đó tương tự như sau:

BOOL done = NO; 
    do { 
     int result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, YES); 
     done = (result == kCFRunLoopRunStopped) || (result == kCFRunLoopRunFinished); 
    } while (!done); 

3) Bây giờ, về quản lý chủ đề mà bạn có thể báo hiệu (gửi tin nhắn) để nhận trước đó nguồn chạy vòng lặp khi cần thiết (và thức dậy vòng lặp chạy trong những chủ đề trong trường hợp nó đang ngủ):

CFRunLoopSourceSignal(runLoopSource); 
    CFRunLoopWakeUp(workerThreadRunLoop); 

Các chi tiết khác có trong số guide của Apple.

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