2013-07-31 2 views
10

iOS에서 어떤 이벤트가 발생할 때까지 NSThread 내부에서 기다리는 방법은 무엇입니까?iOS에서 어떤 이벤트가 발생할 때까지 NSThread에서 기다리는 방법?

예 : NSThread를 생성하고 스레드 루프를 시작했습니다. 스레드 루프 내부에는 메시지 대기열에 메시지가 있는지 여부를 확인하는 조건이 있습니다. 메시지가있는 경우 해당 메소드를 호출하여 일부 작업을 수행하고 그렇지 않으면 메시지 대기열에 새 메시지가 채워질 때까지 기다려야합니다.

어떤 이벤트가 발생할 때까지 기다릴 수있는 API가 있습니까?

어떤 도움을 주셔야합니다.

답변

13

NSCondition을 사용할 수 있습니다. 내가 찾던 정확히 무엇의 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

에서 "준비를위한 테스트"예를 코드를 연결합니다. 위대한 간단하고 깨끗한 예. –

+0

우수한 예 – ashokdy

2

세마포를 사용할 수 있습니다. 아래 예를 보면 논리가 매우 간단합니다. 내 예를 들어, 블록이 백그라운드에서 실행되며 내 메인 스레드가 갈 세마포의 디스패치 신호를 기다립니다. 주된 차이점은 제 경우에는 대기중인 스레드가 주 스레드이지만 세마포어 논리가 여기에 있습니다. 귀하의 경우에이를 쉽게 적용 할 수 있다고 생각합니다.

//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

당신은 run loop sources를 사용할 수 있습니다. 본질적으로 :

1) 보조 작업자 스레드에 생성하고 실행 루프 소스를 설치하고, 이것에 메시지를 보내는 것, 다른 관리 스레드, 작업자 스레드 실행 루프 참조와 함께, 어떻게 든 통과 :

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 

다음은 위에서 언급 한 사용자 정의 루틴이있다 - 당신이 그들을 제공 할 책임이있다 : 작업자 스레드에

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)이 평소 실행 루프, 비슷한 일을 시작 :

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

3) 이제) 필요할 때이 신호를 수 스레드 관리에 (이전에 수신 실행 루프 소스에) 메시지를 전송 (그리고 경우에 그 스레드의 실행 루프를 깨워은 잠 :

CFRunLoopSourceSignal(runLoopSource); 
    CFRunLoopWakeUp(workerThreadRunLoop); 

자세한 내용은 Apple guide에 있습니다.