3

いつでもキャンセルできるようにしたい一連の NSOperations (最大同時実行数を 1 に設定) を実行しているメイン スレッドに NSOperationQueue があります。ボタンを押すと、すべての操作をキャンセルして終了するまで待つようにキューに指示します。これにより、操作キューが空になるまでメインスレッドがハングするはずですが、メインスレッドが無期限にハングします。

これを停止するために使用するコードは次のとおりです。

...
[myQueue cancelAllOperations];
[myQueue waitUntilAllOperationsAreFinished];
return YES; // This line never gets called

注:waitUntilAllOperationsAreFinished以降のプロセスではキューを空にする必要があるため、使用する必要があります。

奇妙なことに、これはデバイス上でのみ発生しています。シミュレーターで実行すると、期待どおりに動作します。

ブレークポイントを監視しており、現在実行中の操作が完了するまで追跡できます。[self isCancelled] を検出し、実行中の処理を停止して、mainメソッドの最後までスキップします。操作でハングする原因が何もないことがわかります。すべての操作をキャンセルすると、他の操作は開始されず、キューは終了するはずです。ブレークポイントを追加して確認しましたが、他の操作は開始されません。

なぜこうなった?

4

3 に答える 3

8

あなたの操作のいずれか(または他のスレッド)で、使用してい-performSelectorOnMainThread:withObject:waitUntilDone:ますか? -waitUntilAllOperationsAreFinishedすべての操作が完了するまで、呼び出されたスレッドをブロックします。アプリケーションの終了時にこれを呼び出している場合、そのスレッドがメインスレッドになる可能性があります。メイン スレッドがブロックされ、操作の 1 つが を使用する-performSelectorOnMainThread:withObject:waitUntilDone:場合、操作が完了しないため、アプリケーションがフリーズします。

私は以前にこれとまったく同じことが起こったことがあります。残念ながら、回避するのはかなり難しいです。

于 2009-12-16T02:46:27.747 に答える
5

メインスレッドを決してブロックしないでください。デッドロックを作成したことに気付いたように、UI のすべての更新を 1 つのことで処理します。

代わりに、次のようなメソッドを作成してみてください。

- (void) notifyOnFinish
{
   [myQueue waitUntilAllOperationsAreFinished];
   [self performSelectorOnMainThread:(queueEmpty) withObject:nil waitUntilDone:NO];
}

次に、コードがある場所で、次のように呼び出します。

[myQueue cancelAllOperations];
[self performSelectorInBackground:@selector(notifyOnFinish) withObject:nil];

また、queueEmpty メソッドでは、キューが空になったときにやりたいことを何でも実行できます。

基本的には、メイン スレッドの代わりにブロックするバックグラウンド スレッドを作成するだけです。

于 2009-12-16T05:14:46.670 に答える
0

おそらく がwaitUntilAllOperationsArefFinishedブロックを引き起こしている可能性があります... への呼び出しの前にすべての操作がキャンセルされて終了しwaitUntilAllOperationsArefFinished、キューがハングして、既に終了している操作が終了するのを待っている可能性があります...?

事実はわかりませんが、 を呼び出さないようにしてくださいwaitUntilAllOperationsArefFinished

于 2009-12-15T23:47:13.963 に答える