Xamarin.Essentials: MainThread

Класс MainThread позволяет выполнять код в основном потоке приложения, а также проверять, выполняется ли конкретный блок кода в основном потоке в конкретный момент.

Общие сведения

Большинство операционных систем, включая iOS, Android и универсальную платформу Windows, используют однопоточную модель для кода, имеющего отношение к пользовательскому интерфейсу. Такая модель необходима для правильной сериализации событий пользовательского интерфейса, например нажатий клавиш и сенсорного ввода. Этот поток может упоминаться как основной потоком, поток, обрабатывающий события от пользовательского интерфейса, или поток пользовательского интерфейса. Недостатком этой модели является то, что весь код с доступом к элементам пользовательского интерфейса должен выполняться в основном потоке приложения.

Иногда приложениям приходится использовать события, которые вызывают обработчик событий во второстепенном потоке выполнения. (Классы Xamarin.EssentialsAccelerometer, 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);

Примечание.

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 для основного потока.

API

Другие видео о Xamarin см. на Channel 9 и YouTube.