2012-01-06 11 views
0

NSOperationサブクラス(PointsOperation)を使用して、アプリのバックグラウンドで計算を実行しています。ユーザーの動作により、これらの計算をキャンセルし、新しい計算を開始する必要があります。その場合は、新しいPointsOperationインスタンスを作成し、最初のインスタンスと同じNSOperationQueueに追加します。 PointsOperationのメインメソッドの最初のものとして、別の操作が既に実行されているかどうかを確認し、取り消します。NSOperation waitUntilFinishedが長時間待機する

操作で共有キャッシュが使用されているため、並列に実行する必要はありません(実行する必要はありません)。したがって、2番目の操作は、最初の操作が完了するまで待機します。メインメソッドの結果のコードは次のようなものになります。

static NSOperation *currentOperation = nil; 
- (void) main 
{ 
    // setting up autorelease pool, catching exceptions, etc 
    @synchronized(lock) { 
     if (currentOperation != nil) { 
     [currentOperation cancel]; 
     [currentOperation waitUntilFinished]; 
     } 
     currentOperation = self; 
    } 
    while (!calculationsFinished && ![self isCancelled]) { 
     // do calculations 
    } 
    currentOperation = nil; 
    // releasing autorelease pool, etc 
} 

このすべてが正常に動作しますが、最初の操作が取り消され、それが終了するのを秒待ち、その後、計算を開始します。

問題は、メインメソッドを終了する最初の操作と、waitUntilFinishedから2番目の操作が終了するまでに3〜10秒かかることです。

誰もこれを前に見て、それについて何をすべきかを知っていますか?

また、waitUntilFinishedの代わりに、2番目の操作を最初の操作に依存させて、 "addDependency:"(メインではなくinitメソッドで)を試みました。これもうまくいきますが、同じ問題があります。第2の操作の開始は、最初のメソッドの終了の数秒です。

答えて

0

この名前のにもかかわらず、cancelメソッドは魔法のように操作をキャンセルしません。

操作をキャンセルしても、直ちにその内容を停止させることはありません。 isCancelledから返された値はすべての操作で予想される ですが、コードではこのメソッドによって返された値 を明示的にチェックし、必要に応じて中止する必要があります。操作のスレッドは関係なく、最後まで実行されませんので、

http://developer.apple.com/library/mac/documentation/Cocoa/Reference/NSOperation_class/Reference/Reference.html

あなたがisCancelledプロパティをチェックするようにコードを書いていない場合は

、あなたはそれをキャンセルするかではありません。

+0

答えをありがとう。上のコードと説明でわかるように、私はisCancelledをチェックします。また、キャンセルの結果、操作が終了したことと、最初の操作のメインメソッドの終了とwaitUntilFinishedからの2番目の操作の間に遅延があることを確認しました。 – fishinear

+0

@fishinear私はそれを忘れてしまって残念です:( – tia

+0

あなたを変えるつもりはありませんが、 '[currentOparation waitUntilFinished]'行の変数のスペルが間違っていて、まだコンパイルされていますか? – tia

0

私はここで問題を再現しようとしましたが、私のコードはこのような遅延なしで正常に動作します。これは私のコードです:二つのカテゴリーに来た時の結果はwaitUntilFinishedで取っ

NSOperationQueue* q = [[NSOperationQueue alloc] init]; 
q.maxConcurrentOperationCount = 4; 
for (int i = 0; i < 10; i++) { 
    [q addOperation:[PointsOperation new]]; 
} 

@interface PointsOperation : NSOperation { 
@private 
    bool calculationsFinished; 
} 

@property (nonatomic, assign) int tag; 

@end 


@implementation PointsOperation 

@synthesize tag; 

static NSOperation *currentOperation = nil; 
static NSString* lock = @"LOCK"; 

- (void) main 
{ 
    NSLog(@"Before autoreleasepool with tag: %d", tag); 
    @autoreleasepool { 
     NSLog(@"Before lock"); 
     // setting up autorelease pool, catching exceptions, etc 
     @synchronized(lock) { 
      if (currentOperation != nil) { 
       NSLog(@"Before cancel"); 
       [currentOperation cancel]; 
       NSLog(@"Before waitUntilFinished"); 
       NSDate* beforeWait = [NSDate date]; 
       [currentOperation waitUntilFinished]; 
       NSLog(@"After waitUntilFinished took %f seconds", [[NSDate date] timeIntervalSinceDate:beforeWait]);     
      } 
      currentOperation = self; 
     } 
     NSLog(@"Before while loop"); 
     int i = 0; 
     while (!calculationsFinished && ![self isCancelled]) { 
      // do calculations 
      [NSThread sleepForTimeInterval:1]; 
      NSLog(@"Inside while loop = %d", i); 
      calculationsFinished = (++i > 10); 
     } 
     NSLog(@"After while loop: i = %d", i); 
     currentOperation = nil; 
     // releasing autorelease pool, etc 
    } 
    NSLog(@"%@", @"End of method"); 
} 

@end 

そして、ここでは、どのように私はそれを使用するのです

After waitUntilFinished took 1.002624 seconds 

After waitUntilFinished took 0.000749 seconds 

これはthに依存します私が考えるコールのタイミング。

可能であれば、あなたのコードのどこかに問題がある可能性があるので、もっと多くのコードを提供するべきでしょう。

関連する問題