Monotouch中的System.ComponentModel.BackgroundWorker - 正确用法?

时间:2011-10-05 10:22:25

标签: c# multithreading xamarin.ios

我正在使用System.ComponentModel.BackgroundWorker来执行一些更长时间运行的任务,最终会更新一些UI元素。

有关此事的问题:

  • 是在UI主线程上执行BackgroundWorker.RunWorkerCompleted,还是在单独的线程中执行?或者有不同的问题:我是否必须在using(NSAutoReleasePool)中嵌入我的代码,并且在使用普通线程时我是否需要InvokeOnMainThread()
  • 我是否必须在NSAutoReleasePool代表中使用BackgroundWorker.DoWork

2 个答案:

答案 0 :(得分:1)

  

在UI主线程上执行BackgroundWorker.RunWorkerCompleted,   还是在一个单独的线程?或者提出不同的问题:我是否必须嵌入我的   使用中的代码(NSAutoReleasePool)并且我必须使用InvokeOnMainThread()   就像使用普通线程时一样?

BackgroundWorker.RunWorkerCompleted在UI线程上运行,前提是在该UI线程上创建了worker,并且您在UI线程上调用了RunWorkerAsync。

更准确地说,BackgroundWorker使用SynchronizationContext.Current在UI线程上运行代码。 WPF,Silverlight,WinForms,Asp.NET在初始化时都安装了SynchronizationContext(例如System.Windows.Forms.WindowsFormsSynchronizationContext)。

如果您的UI框架是一个优秀的.NET公民,它将安装自己的同步上下文,BackgroundWorker将在UI线程上引发事件。

  

我是否必须在BackgroundWorker.DoWork中使用NSAutoReleasePool   委派?

我可以告诉你,DoWork在后台线程上运行。如果要在该后台线程上操作UI元素,则需要按照UI框架的规则进行操作。

根据this thread in the Mono mailing list

  
      
  • 您不必在DoWork处理程序中放置NSAutoreleasePool   除非你正在操纵Cocoa类
  •   
  • 您必须在ProgressChanged处理程序中放置NSAutoreleasePool   避免内存泄漏。似乎运行线程不是主要的   之一。
  •   
  • 您必须在RunWorkerCompleted中放置NSAutoreleasePool   处理程序以避免内存泄漏。好像正在运行的线程不是   主要的一个。
  •   
  • 您可以修改直接标记或进度指标值   处理程序,虽然它们不在主线程上运行(阅读:   危险)。最好的方法是使用InvokeRequired标志和Invoke   避免跨线程问题的方法。
  •   

答案 1 :(得分:1)

BackgroundComponentWorker尚未适用于MonoTouch或Mono for Android,因此它不会对UI线程做任何特殊处理。

任何引发的事件都不会在UI线程上引发,因此您需要手动将它们包装在BeginInvokeOnMainThread中。