MainThread クラスを使用すると、アプリケーションでコードを実行のメイン スレッドで実行させたり、コードの特定のブロックがメイン スレッドで現在実行中であるかどうかを調べたりすることができます。
背景
ほとんどのオペレーティング システム — iOS、Android、ユニバーサル Windows プラットフォームなど — では、ユーザー インターフェイスに関連するコードのためにシングル スレッド モデルが使用されます。 このモデルは、ユーザー インターフェイスのイベント (キーストローク、タッチ入力など) をシリアル化するために必要です。 多くの場合、このスレッドはメイン スレッド、ユーザー インターフェイス スレッド、または UI スレッドと呼ばれます。 このモデルの欠点は、ユーザー インターフェイス要素にアクセスするすべてのコードを、アプリケーションのメイン スレッドで実行させなければならないという点です。
アプリケーションでは、イベント ハンドラーを実行のセカンダリ スレッドで呼び出すイベントを使用することが必要な場合があります。 (Xamarin.Essentials のクラス Accelerometer、Compass、Gyroscope、Magnetometer、OrientationSensor はすべて、より速い速度で使用すると、セカンダリ スレッドに関する情報を返す可能性があります)。イベント ハンドラーからユーザー インターフェイス要素にアクセスする必要がある場合は、そのコードをメイン スレッドで実行させる必要があります。 MainThread クラスを使用すると、アプリケーションでこのコードをメイン スレッドで実行させることができます。
作業開始
この API の使用を始めるには、Xamarin.Essentials の概要ガイドを読み、ライブラリが正しくインストールされてプロジェクトに設定されていることを確認してください。
メイン スレッドでのコードの実行
クラスの Xamarin.Essentials への参照を追加します。
using Xamarin.Essentials;
メイン スレッドでコードを実行するには、静的メソッド MainThread.BeginInvokeOnMainThread を呼び出します。 引数は Action オブジェクトです。これは単に、引数も戻り値も持たないメソッドです。
MainThread.BeginInvokeOnMainThread(() =>
{
// Code to run on the main thread
});
また、メイン スレッドで実行させる必要があるコード用に、個別のメソッドを定義することもできます。
void MyMainThreadCode()
{
// Code to run on the main thread
}
こうすると、BeginInvokeOnMainThread メソッド内でこのメソッドを参照することで、これをメイン スレッドで実行させることができます。
MainThread.BeginInvokeOnMainThread(MyMainThreadCode);
Note
Xamarin.Forms には、呼び出されたメソッドがある Device.BeginInvokeOnMainThread(Action) これは MainThread.BeginInvokeOnMainThread(Action) と同じ処理を行います。
Xamarin.Forms アプリではどちらのメソッドも使用できますが、呼び出し元のコードが他にも Xamarin.Forms に依存する必要があるかどうかを検討してください。 ない場合は、MainThread.BeginInvokeOnMainThread(Action) が適切な選択であると考えられます。
コードがメイン スレッドで実行されているかどうかの判断
MainThread クラスを使用すると、アプリケーションで、コードの特定のブロックがメイン スレッドで実行中であるかどうかを調べることもできます。 IsMainThread プロパティを呼び出すコードがメイン スレッドで実行されている場合、プロパティは true を返します。 プログラムでこのプロパティを使用して、メイン スレッド用またはセカンダリ スレッド用に別のコードを実行させることができます。
if (MainThread.IsMainThread)
{
// Code to run if this is the main thread
}
else
{
// Code to run if this is a secondary thread
}
BeginInvokeOnMainThread を呼び出す前に、コードがセカンダリ スレッドで実行されているかどうかをチェックする必要があるか疑問に思うかもしれません。たとえば、次のような場合です。
if (MainThread.IsMainThread)
{
MyMainThreadCode();
}
else
{
MainThread.BeginInvokeOnMainThread(MyMainThreadCode);
}
コードのブロックが既にメイン スレッドで実行されている場合、このチェックによってパフォーマンスが向上するのではないかと思うかもしれません。
しかし、このチェックは必要ではありません。 プラットフォームによる BeginInvokeOnMainThread の実装自体によって、呼び出しがメイン スレッドで行われたかどうかが確認されます。 不要な BeginInvokeOnMainThread を呼び出す場合のパフォーマンスの低下はごくわずかです。
他の方法
MainThread クラスには、他にも次に示す static メソッドが含まれています。これらのメソッドを使用すれば、バックグラウンド スレッドからユーザー インターフェイス要素とやりとりすることができます。
| メソッド | 引数 | 戻り値 | 目的 |
|---|---|---|---|
InvokeOnMainThreadAsync<T> |
Func<T> |
Task<T> |
メイン スレッド上で Func<T> を呼び出し、それが完了するまで待機します。 |
InvokeOnMainThreadAsync |
Action |
Task |
メイン スレッド上で Action を呼び出し、それが完了するまで待機します。 |
InvokeOnMainThreadAsync<T> |
Func<Task<T>> |
Task<T> |
メイン スレッド上で Func<Task<T>> を呼び出し、それが完了するまで待機します。 |
InvokeOnMainThreadAsync |
Func<Task> |
Task |
メイン スレッド上で Func<Task> を呼び出し、それが完了するまで待機します。 |
GetMainThreadSynchronizationContextAsync |
Task<SynchronizationContext> |
メイン スレッドの SynchronizationContext を返します。 |