2

NSOperation20 の URL からいくつかの画像 (20 など) をダウンロードすることを目標に作成しました。そのため、このNSOperation中に 20 個を作成AFImageRequestOperationし、それらを に追加してキューNSOperationQueueに呼び出します。-waitUntilAllOperationsAreFinished

問題は、待たずにすぐに戻ることです。ここにコードがあります

- (void)main {
    NSArray *array = [I have the 20 links stored in this array];

    self.queue = [[NSOperationQueue alloc]init];
    self.queue.maxConcurrentOperationCount = 1;

    for (int i = 0; i < array.count; i++) {                
        NSURL *url = [NSURL URLWithString:[array objectAtIndex:i]];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];

        AFImageRequestOperation *op = [AFImageRequestOperation imageRequestOperationWithRequest:request imageProcessingBlock:^UIImage *(UIImage *image) {
            return image;
        } success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
        // SUCCESS BLOCK (not relevant)
        } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
        // FAILURE BLOCK (not relevant)
        }];

        [self.queue addOperation:op];
    }

    [self.queue waitUntilAllOperationsAreFinished]; // Here is the problem it doesn't wait
    DDLogWarn(@"-- %@ FINISHED --", self);

}

コンソールでは、DDLogWarn(@"-- %@ FINISHED --", self);すべての操作が開始される前に出力されるため、私の推測では、waitUntilAllOperationsAreFinishedはジョブを実行せず、待機もしていませんでしたが、その後も 20 の操作がまだ実行されているため、mainまだ返されていない可能性があります。だから私はもう何を考えるべきか分からない。

EDIT 1:実際には、すべての操作が完了するまでスレッドをDDLogブロックしているため、成功と失敗の内部がブロックされているかどうか疑問に思っています。waitUntilAllOperationsAreFinishedそれは、なぜ私が何も起こっていないのか、そしてすべてが突然に見えないのかを説明するかもしれません.

4

2 に答える 2

5

NSOperationあなたと同様の理由で、 other を含むを作成すると便利であることがわかりましたNSOperations。たとえば、大きなタスクを構成する小さなタスクがたくさんあり、大きなタスクを 1 つの単位として扱い、それが完了したときに通知を受けたいと考えています。完了しました。また、大きなタスクの実行をシリアル化する必要があるため、一度に実行されるのは 1 つだけですが、それぞれの大きなタスクが実行されると、そのタスク内で複数の同時操作を実行できます。

あなたと同じようにNSOperation、大きなタスクを管理するために を作成するのは良い方法だと思われました。さらに、これを行うべきではないと書かれているドキュメントを読んだこともありませんでした。

結局、コードが機能しているように見えるので、引き続き NSOperation を使用できます。

状況によっては、スレッドをブロックすることが妥当な場合があります。ブロックが合理的ではないが、NSOperation を引き続き使用したい場合は、「同時実行」を作成する必要があります。「同時実行プログラミング ガイド: 同時実行のための操作の構成NSOperation」を参照してください。

一度に 1 つのイメージ ダウンロードのみを許可する場合は、@jackslashs の提案を使用して操作の終了を通知できます。または、同時イメージ ダウンロードを許可する場合は、単一のイメージ ダウンロードをNSBlockOperation最終操作として使用-[NSOperation addDependency:]し、それを依存させるために使用できます。他のすべての操作で、最後に実行されるようにします。

すべてが終了したというシグナルを受け取ったら、ドキュメントに記載されているように適切にisFinishedおよびisExecutingフラグを設定して、 main を完成させることができますNSOperation

確かに、これにはある程度の複雑さがありますが、その複雑さがコードの内部に隠さNSOperationれると、私の場合のように外部のコードがより単純になる可能性があるため、役立つ場合があります。

Concurrent を作成するNSOperation場合は、Apple のサンプル コードLinkedImageFetcher:QRunLoopOperationが出発点として役立ちます。

于 2013-02-13T13:12:12.663 に答える
1

このコードは、の中にある必要はありませんNSOperation。代わりに、操作キューを持つクラス(おそらくシングルトン)を作成し、呼び出されるメソッドを作成します

-(void)getImagesFromArray:(NSArray *)array

またはそのようなもので、上記のコードはそのキューへのエンキューで正常に機能します。を呼び出す必要はありませんwaitUntilAllOperationsAreFinished。それはブロッキングコールです。キューの最大操作数が1の場合、すべてのネットワーク操作を追加したら、キューに別の操作を追加できます。実行すると、他のすべての操作が終了したことがわかります。最後に単純なブロック操作を追加するだけで済みます。

//add all the network operations in a loop
[self.operationQueue addOperation:[NSBlockOperation blockOperationWithBlock:^{
    //this is the last operation in the queue. Therefore all other network operations have finished
}]];
于 2013-02-12T12:55:53.130 に答える