2012-03-28 12 views
3

私はこの中にnsthread、whileループを持っています。メインメソッドの「スレッドセーフ」キューからオブジェクトを取得しています。このnsthreadオブジェクトを含むUIViewControllerを離れるとき、私はnsthreadキャンセルメソッドを呼び出しますが、それは "queueLock" NSConditionによってロックされているので停止しません。このUIViewControllerに戻ると、新しいnsthreadが作成され、オブジェクトがキューから取得されますが、以前のスレッドはまだ終了し、両方がキューから同じオブジェクトを使用しようとすると、メモリ管理の問題が発生します。私の質問は、私はUIViewControllerを離れるとき、このスレッドをどのように止めるべきかです。iOS - Objective-C - 待機中のNSThreadを停止するにはどうすればいいですか?

NSThread主な方法:

NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 
while ([self isCancelled] == NO) { 
    RenderRequest *renderRequest = [queue get]; 
    [self doRender:renderRequest]; 
    [renderRequest release];  
} 

[pool drain]; 

このキュークラスのgetメソッドは次のとおりです。

- (id) get { 
    id toRet = nil; 
    [queueLock lock]; 
    @try { 
     while ([queueContents count] == 0) { 
      [queueLock wait]; 
     } 

     toRet = [queueContents lastObject]; 
     [queueContents removeLastObject]; 
    } 

    @finally { 
     [queueLock unlock]; 
     return toRet; 
    } 
} 

ありがとう!

答えて

1

を待って停止するqueueLockを通知し、これはあなたを助けることができることを望むことができます

NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 

while ([self isCancelled] == NO) 
{ 
    RenderRequest *renderRequest = [queue get]; 
    if (renderRequest == nil) break; // should stop 
    [self doRender:renderRequest]; 
    [renderRequest release];  
} 

[pool drain]; 

メインスレッド:)

デモ.h

#import <Foundation/Foundation.h> 

@interface test : NSObject 
{ 
    NSCondition *queueCondition; 
    NSThread *queueThread; 

    NSMutableArray *queueTask; 

    NSTimer *timer; 
} 
- (id)init; 
@end 

demo.m

#import "demo.h" 

@interface demo (PrivateMethods) 
- (void)threadTest; 
- (void)cancelThread; 
- (void)addTask; 
@end 


@implementation demo 

- (id)init 
{ 
    self = [super init]; 
    if (self) { 
     if (!queueThread) { 
      if (!queueCondition) { 
       queueCondition = [[NSCondition alloc] init]; 
      } 

      if (!queueTask) { 
       queueTask = [[NSMutableArray alloc] initWithCapacity:5]; 
      } 

      queueThread = [[NSThread alloc] initWithTarget:self selector:@selector(threadTest) object:nil]; 
      [queueThread start]; 

      [self performSelector:@selector(cancelThread) withObject:nil afterDelay:10]; 

      if (!timer) { 
       timer = [[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(addTask) userInfo:nil repeats:YES] retain]; 
      } 
     } 
    } 
    return self; 
} 

- (void)dealloc 
{ 
    [queueThread release]; 
    [queueCondition release]; 
    [queueTask release]; 
    [timer invalidate]; 
    [timer release]; 
    [super dealloc]; 
} 

- (void)threadTest 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    while (![[NSThread currentThread] isCancelled]) { 
     [queueCondition lock]; 
     [queueCondition wait]; 

     if ([queueTask count] == 0) { 
      [queueCondition unlock]; 
      continue; 
     } 

     NSString *str = nil; 
     while ((str = [queueTask lastObject])) { 
      NSLog(@"getTask: %@", [queueTask lastObject]); 
      [queueTask removeLastObject]; 

     } 

     [queueCondition unlock]; 
    } 
    NSLog(@"threadTest end"); 
    [pool drain]; 
} 

- (void)addTask 
{ 
    [queueCondition lock]; 
    if (!queueTask) { 
     queueTask = [[NSMutableArray alloc] initWithCapacity:5]; 
    } 
    [queueTask addObject:@"new task"]; 
    [queueCondition signal]; 
    NSLog(@"add: new task"); 
    [queueCondition unlock]; 
} 

- (void)cancelThread 
{ 
    [timer invalidate]; 

    [queueThread cancel]; 

    [queueCondition lock]; 
    [queueCondition signal]; 
    [queueCondition unlock]; 
} 
@end 
+0

ありがとう、私はそれを試してみましょう。 –

+1

謝辞をありがとう!私はあなたがNSThreadを理解するために書いたこの素敵なデモとデータをキューに入れる方法を使用しました。誰もが今GCDを指摘していますが、NSThread 'do it by hand'オプションを覚えておくことが重要だと思います。 – LEO

0
- (id) get 
{ 
    id toRet = nil; 
    [queueLock lock]; 
    @try 
    { 
     while ([queueContents count] == 0) 
     { 
      [queueLock wait]; 
      if ([self isCancelled]) return nil; // stop waiting 
     } 

     toRet = [queueContents lastObject]; 
     [queueContents removeLastObject]; 
    } 
    @finally 
    { 
     [queueLock unlock]; 
     return toRet; 
    } 
} 

、あなたがスレッドをキャンセルして、私は簡単なデモを書いた

+0

ありがとうございました。私はこれを試みたが、私はUIViewControllerを開いて2回目には、[[Type Aリリースではない]:[deallocatedに送られたメッセージ]を取得し、[プールドレイン]行にエラーがあり、最初のスレッドはまだ存在します。私はUIViewControllerのviewDidDisappearメソッドでスレッドキャンセルメソッドを呼び出します。 –

関連する問題