17

多くのハンドラーを持つことができます: touches ハンドラー、UIControl ハンドラー (ボタン、スライダー)、performSelector、CADisplayLink、NSTimer イベント、Gesture Recognizer、加速度計ハンドラー、UIView アニメーション完了ブロック、およびその他のハンドラー。

それらはすべて同じスレッドにありますか?つまり、同時に実行できるのは 1 つだけですか?

他のメソッドまたはハンドラーが別のスレッドの一部であり、競合状態を引き起こす可能性はありますか?

4

1 に答える 1

16

一般に、iOS の単純なアプリケーションのほとんどは、メイン スレッドでほぼすべてのアクションを実行する傾向があります。お気づきのように、マルチスレッド化を図に取り入れた瞬間に、注意すべき別のトリッキーな問題が追加されます。多くの開発者は、この追加された複雑さに煩わされたくないか、GCD や一般的なスレッド化に慣れていないため、バックグラウンド スレッドや GCD キューで何かを行うことを避けています。

質問にリストした項目のいくつかは、UIKit との対話を伴います。一般に、これらの対話はメイン スレッドで発生する必要があります (ただし、iOS 4.x では、バックグラウンドでいくつかの描画機能を実行する機能が追加されました)。メインスレッドでタッチおよびその他の関連イベントを受け取ります。インターフェイスのほとんどの側面を更新する場合、安全な方法はメイン スレッドでこれらの更新を実行することです。

タイマー (NSTimer、CADisplayLink) は、バックグラウンド スレッドで動作する NSRunLoop にアタッチすることにより、その更新をバックグラウンド スレッドで起動できます。人々がこれを行うことはめったにありませんが、それは可能です。通常、人々はメインの実行ループでタイマーを構成します。これにより、メイン スレッドでコールバックが配信されます。

アニメーションを実行するとき、アニメーション自体はバックグラウンド スレッドで実行されます (メイン スレッドを別のものでブロックしている間、アニメーションは停止しないことがわかります) が、ほとんどの場合、メイン スレッドで完了ブロックまたはコールバックを受け取ります。それらが完了したらスレッドします。私の記憶が正しければ、これには 1 つまたは 2 つの例外があり、それらは Apple のドキュメントにそのように記載されています。これらのコールバックをメイン スレッドでトリガーすることは、舞台裏で何が起こっているのかを理解していない可能性のある開発者に対処する場合に安全な方法です。

とはいえ、アプリケーションにマルチスレッドを追加するのには十分な理由があります。すべてのユーザー インターフェイスの更新とタッチ インタラクションはメイン スレッドで発生するため、計算コストが高いものや単に実行に時間がかかるものがある場合、これをメイン スレッドで実行すると、応用。これはひどいユーザー エクスペリエンスであるため、このタスクをバックグラウンド スレッドに移動して、ユーザーがアプリケーションと対話し続けられるようにする必要があります。さらに、複数のコアを搭載した iOS デバイスが毎日出荷されており、これらのコア間でワークロードのバランスを取り、このハードウェアを効率的に使用するには、ある程度の同時処理が必要です。

コードをマルチスレッド化する際のベスト プラクティスについて書かれた本がいくつかありますが、ここではこれに関する多くの質問を見つけることができるので、ここではあまり詳しく説明しません。私が言えることは、Apple のConcurrency Programming Guideを読み、Grand Central Dispatch を扱った過去 2 年間の WWDC ビデオを見るべきだということです。GCD により、Apple は効率的かつ (比較的) 安全な方法でアプリケーションにマルチスレッドを追加することを非常に簡単にしました。

たとえば、分子構造の詳細なレンダリングを実行するオープン ソースの iOS アプリケーションがあります。バックグラウンドの GCD キューで各フレームをレンダリングするのは、処理に 1/60 秒以上かかる場合があるためです。そのような場合、これがすべてメイン スレッド上にあると、タッチ イベントがドロップされ、インターフェイスが途切れる原因になります。 . さらに、新しいマルチコア デバイスで実行する場合、これを行うことで最大 40% のパフォーマンス向上が見られました。競合状態を避けるために、特定のブロックがどのスレッドで実行されているかに関係なく、一度に 1 つのアクションだけがリソースを使用できるように、シリアル ディスパッチ キューで共有データ構造とコンテキストとの対話をラップします。これには数行のコードを追加するだけで済みましたが、パフォーマンスとユーザー エクスペリエンスのメリットは非常に大きなものでした。

于 2012-06-08T18:10:23.813 に答える