2014-01-15 4 views
0

내 커맨드 라인 프로그램의 주요 기능으로, NSThread 하위 클래스의 새 인스턴스를 만들고 다른 스레드에서 타이머를 실행하는 start을 호출합니다. 사용자가 타이머를 멈추고 싶다면, "stop"을 입력하면 스레드를 끝내고 싶습니다.메인에서는 새로운 NSThread를 생성하고, 조건이 충족 될 때 메인의 나중 시점에서 스레드를 중지하려고합니다. 방법?

어떻게해야합니까? 나는 cancel을 스레드에 호출해야한다는 것을 모으고 있으며, NSThread 하위 클래스의 서브 클래스 검사에서 이 YES 인 경우를 제외하고는 처음에는 start을 호출 할 때 메인이 호출 될 때까지만 호출됩니다. 다른 곳에서 isCancelled을 확인하여 [NSThread exit]으로 전화를 걸 수는 없습니다.

이 NSThread를 종료하려면 어떻게해야합니까?

+0

주 함수가 반환 된 후 NSThread가 종료됩니다. – CouchDeveloper

+0

@CouchDeveloper 이전에 해지하고 싶습니다. –

+0

'main' *에서 조기에 반환해야하는 유일한 옵션은 @random에 의해 이미 정확하게 설명되어 있습니다. – CouchDeveloper

답변

3

NSThread 하위 클래스에서 isCancelled을 확인하십시오. NSThread 하위 클래스에서 코드 전체에 걸쳐 isCancelled을 확인합니다. cancel으로 전화 할 때 NSThread 서브 클래스는 isCancelled에 대한 확인을받을 때까지 계속 실행됩니다. 당신이 무엇을 할 isCancelledcancel 전화 isCancelled 체크를 호출하고 가능한 한 빨리 종료 할 때 희망 여러 장소를 확인하는 것입니다. 귀하의 예제 코드에서

당신은 내가 같이하는 TimerThread.m를 변경 게시하고 그것을 잘 작동합니다 다음과 같이 다양한 의견을 바탕으로

#import "TimerThread.h" 
#import "Giraffe.h" 

@interface TimerThread() { 
    Giraffe *giraffe; 
} 

@end 

@implementation TimerThread 

- (void)main { 

    if (self.isCancelled) 
     return; 

    giraffe = [[Giraffe alloc] init]; 

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

    [[NSRunLoop currentRunLoop] run]; 
} 

- (void)calculate:(NSTimer*)timer { 
    if (self.isCancelled) { 

     [timer invalidate]; 

     return; 
    } 

    [giraffe calculateValues:timer]; 
} 

@end 
+0

하지만 내 NSThread 하위 클래스는 한 번만 호출되며 내가 말할 수있는 한 한 번만 실행이 진행됩니다. –

+0

'NSThread'는 메인 기능이 완료되면 종료됩니다. 완료되면 명시 적으로 '취소'를 호출 할 필요가 없습니다. – random

+0

코드를 게시 할 수 있습니까?'main '메소드 밖에서'isCancelled'를 체크 할 다른 메소드가 있다는 것을 의미합니까? – random

1

, 당신은 가능성이 주요 방법을 원하는 :

+ (void) threadMain 
{ 
    @autoreleasepool { 
     [[NSThread currentThread] setName:@"WorkerThread.sharedThread"]; 
     NSRunLoop* runLoop = [NSRunLoop currentRunLoop]; 
     [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode]; 
     BOOL done = NO; 
     while (!done) { 
      @autoreleasepool { 
       [runLoop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]; 
       // check termination status: 
       done = ...; 
      } 
     } 
    } 
} 

몇 가지 설명 :

  • [runLoop addPort:port] 전자 실행 루프에 적어도 하나의 이벤트 소스가 있는지 확인하십시오. 그렇지 않으면 실행 루프가 조기에 반환 될 수 있습니다.

  • 처리 된 모든 이벤트 소스가 끝나면 실행 루프가 반환됩니다. 즉, 일이 발생한 후에 상태를 확인할 수 있습니다 (예 :이 실행 루프에서 예정된 타이머, 즉 모드가 NSDefaultRunLoopMode 인 경우). 당신이 오토 릴리즈 풀을하지 않는 한이 쌓아 수 있습니다 - [NSDate distantFuture] 객체를 오토 릴리즈 반환 이후

  • 내부 오토 릴리즈 풀

    이 필요합니다.

  • 변수 은이 스레드에서 실행되는 코드에서 설정해야합니다. 그렇지 않으면 다른 스레드에서 변경 한 내용이이 스레드에서 "표시"되도록하려면 메모리 장벽이나 다른 동기화 프리미티브가 필요합니다.

+0

+1 잘 @CouchDeveloper 이것은 실제로 기존 프로젝트를 조정할 수있었습니다 : P – random

+0

@random 호기심에서 : 당신은 무엇을 고칠 수 있습니까? – CouchDeveloper

+0

나는 많은 양의 데이터를 CoreData로 파싱하는 최적의 방법을 가지고 놀았으며 작업 부하를 공유하는 NSOperation 하위 클래스가있었습니다. 나는 그에게 제공 한 솔루션과 비슷한 솔루션을 사용하고 있었지만, 게시 한 솔루션을 다른 솔루션으로 이끌어 냈습니다. :) – random