Xamarin.iOS 中的线程处理

Xamarin.iOS 运行时使开发人员能够访问 .NET 线程 API,无论是使用线程 (System.Threading.Thread, System.Threading.ThreadPool) 时显式访问,还是使用异步委托模式或 BeginXXX 方法时隐式访问,以及支持任务并行库的全系列 API。

Xamarin 强烈建议使用任务并行库 (TPL) 来生成应用程序,原因如下:

  • 默认的 TPL 计划程序会将任务执行委托给线程池,而线程池又会在进程发生时动态增加所需的线程数量,同时避免出现过多线程最终争用 CPU 时间的情况。
  • 从 TPL 任务的角度考虑操作会更容易。 可以轻松地操作任务、安排任务、序列化任务的执行或使用一组丰富的 API 并行启动任务。
  • 它是使用新的 C# 异步语言扩展进行编程的基础。

线程池将根据系统上可用的 CPU 核心数、系统负载和应用程序需求,根据需要缓慢增加线程数。 可以通过调用 System.Threading.ThreadPool 中的方法或使用默认 System.Threading.Tasks.TaskScheduler(并行框架的一部分)来使用此线程池

通常,开发人员在需要创建响应式应用程序并且不想阻止主 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 运行时将创建和释放对象。 如果将对象标记为“自动释放”,Objective-C 运行时会将这些对象释放到线程的当前 NSAutoReleasePool。 Xamarin.iOS 为 System.Threading.ThreadPool 中的每个线程和主线程创建一个 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,因此你不必再自己提供。