我正在使用System.ComponentModel.BackgroundWorker
来执行一些更长时间运行的任务,最终会更新一些UI元素。
有关此事的问题:
BackgroundWorker.RunWorkerCompleted
,还是在单独的线程中执行?或者有不同的问题:我是否必须在using(NSAutoReleasePool)
中嵌入我的代码,并且在使用普通线程时我是否需要InvokeOnMainThread()
?NSAutoReleasePool
代表中使用BackgroundWorker.DoWork
?答案 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中。