1

シリアル キューにディスパッチされるいくつかのタスクと、特にグループにディスパッチされるいくつかのタスクがあります。これらのタスクがディスパッチされた後、それらが既に実行されている場合でも、それらをキャンセルするオプションをユーザーに提供したいと思います。

キューに入れられたタスクをキャンセルする方法が見つからないので、quitRender などと呼ばれるブール値のフラグを作成し、このフラグが true かどうかをテストしてレンダリングを終了できると想像しましたが、これは機能せず、私の説明は次のとおりです。タスクが起動されるとフラグ quitRender は NO であるため、タスクはブロックで実行され、ブロックは開始時の値を凍結するため、ブロックは変更を認識せず、決して終了しません。

次に、別のアプローチを試しました。次のようなメソッドを作成します

- (BOOL) cancelRender {
    return quitRender;
}

それは実行され、変数の現在の値をブロックに送信しますが、どうやらブロックはquitRenderに対して引き続きNOと見なします。

何か不足していますか?これを機能させるにはどうすればよいですか?

ありがとう。

4

3 に答える 3

4

このような状況では、__block ストレージ修飾子が役立つ場合があります。

__block BOOL quitRender = NO;

ブロックから変数を変更できるようにし、ブロックは変更された変数を見ることができます。ただし、__block 変数へのアクセスはスレッドセーフではないことに注意してください。

アトミック関数は、変数をアトミックとして確実にアクセスするために推奨されます。

また、ブロックから ivar を使用することもできます。変数がアトミック属性のプロパティである場合、アクセスはスレッドセーフです。

quitRender 変数をどのように使用しますか?

編集

__block int32_t quitRender = 0;

/* set */
OSAtomicOr32(1, &quitRender);

/* test */
if (quitRender) {
于 2011-03-10T09:57:51.120 に答える
1

__block保留中の操作をキャンセルする必要があることを示すために、コードの本体がそれを変更できるため 、quitRender 変数をストレージ クラス変数にすることで正しい軌道に乗っています。

ただし、他の人が示唆しているように、キャンセルは本質的に競争が激しいため、スレッドセーフにすることに問題はありません。変数が TRUE に設定される直前にブロックの実行を開始 (およびキャンセル チェックを実行) することができますOSAtomic()。この場合、キャンセル フラグは FALSE から TRUE 状態にしか移行できないためです。

なんらかの理由でブロック クラス ストレージの管理が面倒な場合 (複数の操作がすべてキャンセル可能であるとします)、キューによって管理されているデータ構造の中にキャンセル フラグを置き、単純にチェックします。キュー自体が、キュー上のすべての操作がキャンセルされたことを示す適切な場所である場合は、 を使用dispatch_{set,get}_specific()してこれをキュー自体に格納することもできます。HTH。

于 2011-11-01T00:03:24.073 に答える
0

特定のクラスのすべてのタスクを終了したい場合は、quitRender フラグを、ブロック コードがフリーズしない揮発性の静的 BOOL グローバル変数にすることを試みることができます。

静的グローバル変数を getter と setter でラップして、コードを簡潔にすることができます。

于 2011-03-10T06:30:31.147 に答える