7

可能な限り最も効率的な方法でいくつかのコア イメージ フィルターを実行しようとしています。大きな画像をレンダリングするときに発生するメモリ警告とクラッシュを回避しようとしています。Apple の Core Image Programming Guide を見ています。マルチスレッドに関しては、「各スレッドは独自の CIFilter オブジェクトを作成する必要があります。そうしないと、アプリが予期しない動作をする可能性があります。」

これは何を意味するのでしょうか?

実際、バックグラウンド スレッドでフィルターを実行しようとしているので、メイン スレッドで HUD を実行できます (以下を参照)。これは、coreImage のコンテキストで意味がありますか? コア イメージは本質的に GCD を使用していると思います。

//start HUD code here, on main thread

// Get a concurrent queue form the system
dispatch_queue_t concurrentQueue =
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{

    //Effect image using Core Image filter chain on a background thread

    dispatch_async(dispatch_get_main_queue(), ^{

        //dismiss HUD and add fitered image to imageView in main thread

    });

});

Apple ドキュメントからの詳細:

スレッドセーフの維持

CIContext および CIImage オブジェクトは不変です。つまり、それぞれをスレッド間で安全に共有できます。複数のスレッドが同じ GPU または CPU の CIContext オブジェクトを使用して、CIImage オブジェクトをレンダリングできます。ただし、これは変更可能な CIFilter オブジェクトには当てはまりません。CIFilter オブジェクトは、スレッド間で安全に共有できません。アプリがマルチスレッドの場合、各スレッドは独自の CIFilter オブジェクトを作成する必要があります。そうしないと、アプリが予期しない動作をする可能性があります。

4

1 に答える 1

12

別の言い方ができるかどうかわかりません。各バックグラウンド スレッドは、フィルター チェーン内に独自のバージョンの CIFilter オブジェクトを作成する必要があります。これを実現する 1 つの方法は、バックグラウンド操作ごとにフィルター チェーンのコピーを作成することですdispatch_async(...)。あなたが投稿したコードでは、次のようになります。

//start HUD code here, on main thread
// Assuming you already have a CIFilter* variable, created on the main thread, called `myFilter`
CIFilter* filterForThread = [myFilter copy];
// Get a concurrent queue form the system
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
    CIFilter filter = filterForThread;

    // Effect image using Core Image filter chain on a background thread

    dispatch_async(dispatch_get_main_queue(), ^{

        //dismiss HUD and add fitered image to imageView in main thread

    });

});
[filterForThread release];

ここで何が起こるかというと、それfilterForThreadは のコピーですmyFilterfilterForThread渡したブロック内で参照するdispatch_asyncと、そのブロックが保持されfilterForThread、次に呼び出しスコープが解放され、ブロックfilterForThreadへの概念的な所有権の転送が効果的に完了しfilterForThreadます (参照が残っているのはブロックだけであるため)。filterForThreadブロックが実行されるスレッドに対してプライベートと考えることができます。

ここでのスレッドの安全性の要件を満たすには、これで十分なはずです。

于 2013-01-08T14:23:18.720 に答える