Потоки в Xamarin.iOS
Среда выполнения Xamarin.iOS предоставляет разработчикам доступ к API потоков .NET, как явным образом при использовании потоков (System.Threading.Thread, System.Threading.ThreadPool
), так и неявно при использовании асинхронных шаблонов делегатов или методов BeginXXX, а также полного диапазона API, поддерживающих библиотеку параллельных задач.
Xamarin настоятельно рекомендует использовать библиотеку параллельных задач (TPL) для создания приложений по нескольким причинам:
- Планировщик TPL по умолчанию делегирует выполнение задачи пулу потоков, что, в свою очередь, будет динамически увеличивать количество потоков, необходимых при выполнении процесса, избегая сценария, в котором слишком много потоков в конечном итоге конкурируют за время ЦП.
- Проще думать об операциях с точки зрения задач TPL. Вы можете легко управлять ими, планировать их выполнение, сериализовать их выполнение или запускать многие параллельно с богатым набором API.
- Это основа программирования с новыми расширениями языка асинхронного языка C#.
Пул потоков будет медленно увеличивать количество потоков по мере необходимости в зависимости от количества ядер ЦП, доступных в системе, загрузки системы и требований приложения. Этот пул потоков можно использовать либо путем вызова методов в System.Threading.ThreadPool
или с помощью по умолчанию System.Threading.Tasks.TaskScheduler
(часть Parallel Framework).
Как правило, разработчики используют потоки, когда им нужно создавать адаптивные приложения, и они не хотят блокировать основной цикл выполнения пользовательского интерфейса.
Разработка адаптивных приложений
Доступ к элементам пользовательского интерфейса должен быть ограничен тем же потоком, который выполняет основной цикл для приложения. Если вы хотите внести изменения в основной пользовательский интерфейс из потока, следует ставить код в очередь с помощью 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 среда выполнения создаст и освобождает объекты. Если объекты помечены для автоматического выпуска, Objective-C среда выполнения выпустит эти объекты в текущий поток NSAutoReleasePool
. Xamarin.iOS создает один NSAutoRelease
пул для каждого потока из System.Threading.ThreadPool
основного потока. Это расширение охватывает все потоки, созданные с помощью taskScheduler по умолчанию в System.Threading.Tasks.
Если вы создаете собственные потоки, используя их, System.Threading
необходимо предоставить собственный NSAutoRelease
пул, чтобы предотвратить утечку данных. Для этого просто упаковайте поток в следующий фрагмент кода:
void MyThreadStart (object arg)
{
using (var ns = new NSAutoReleasePool ()){
// Your code goes here.
}
}
Примечание. Так как Xamarin.iOS 5.2 вам больше не нужно предоставлять собственный NSAutoReleasePool
, так как он будет предоставлен автоматически для вас.