Xamarin.iOS でのスレッド処理
Xamarin.iOS ランタイムを使用すると、開発者は、スレッド (System.Threading.Thread, System.Threading.ThreadPool
) を使用する場合は明示的に、非同期デリゲート パターンまたは BeginXXX メソッドを使用する場合は暗黙的に .NET スレッド処理 API にアクセスでき、タスク並列ライブラリをサポートする API の全範囲にもアクセスできます。
Xamarin でアプリケーションをビルドする場合は、次のような理由から、タスク並列ライブラリ (TPL) を使用することを強くお勧めします。
- 既定の TPL スケジューラは、タスクの実行をスレッド プールに委任します。これにより、多くのスレッドが CPU 時間を奪い合うようなシナリオを回避しながら、プロセスの実行時に必要なスレッドの数が動的に増加します。
- TPL タスクの観点から操作を考える方が簡単です。 豊富な API セットを使用して、これらのタスクの操作、スケジュール設定、実行のシリアル化、多数の並列起動を簡単に行うことができます。
- これは、新しい C# 非同期言語拡張機能を使用したプログラミングの基礎です。
スレッド プールは、システムで使用可能な CPU コアの数、システムの負荷、アプリケーションの需要に基づいて、必要に応じてスレッドの数を徐々に増やします。 このスレッド プールを使用するには、System.Threading.ThreadPool
でメソッドを呼び出すか、既定の System.Threading.Tasks.TaskScheduler
(Parallel Frameworks の一部) を使用します。
通常、開発者は応答性の高いアプリケーションを作成する必要があり、メイン UI 実行ループをブロックしたくない場合にスレッドを使用します。
応答性の高いアプリケーションの開発
UI 要素へのアクセスは、アプリケーションのメイン ループを実行しているのと同じスレッドに制限する必要があります。 スレッドからメイン UI に変更を加える場合は、次のように NSObject.InvokeOnMainThread を使用してコードをキューに入れる必要があります。
MyThreadedRoutine ()
{
var result = DoComputation ();
// we want to update an object that is managed by the main
// thread; To do so, we need to ensure that we only access
// this from the main thread:
InvokeOnMainThread (delegate {
label.Text = "The result is: " + result;
});
}
上記では、アプリケーションをクラッシュさせる可能性のある競合状態を引き起こすことなく、メイン スレッドのコンテキストでデリゲート内のコードを呼び出します。
スレッド処理とガベージ コレクション
実行の過程で、Objective-C ランタイムはオブジェクトを作成して解放します。 オブジェクトに "auto-release" のフラグが設定されている場合、Objective-C ランタイムはそれらのオブジェクトをスレッドの現在の NSAutoReleasePool
オブジェクトに解放します。 Xamarin.iOS は、System.Threading.ThreadPool
のすべてのスレッドとメイン スレッドに対して 1 つの NSAutoRelease
プールを作成します。 これは、System.Threading.Tasks の既定の TaskScheduler を使用して作成されたすべてのスレッドをカバーします。
System.Threading
を使用して独自のスレッドを作成する場合は、データの漏えいを防ぐために独自の NSAutoRelease
プールを提供する必要があります。 これを行うには、次のコードでスレッドをラップするだけです。
void MyThreadStart (object arg)
{
using (var ns = new NSAutoReleasePool ()){
// Your code goes here.
}
}
注: Xamarin.iOS 5.2 以降では、NSAutoReleasePool
が自動的に提供されるため、独自のものを提供する必要はありません。