I'm using System.ComponentModel.BackgroundWorker
to execute some longer running task that - in the end - will update some UI elements.
Questions regarding this:
- Is
BackgroundWorker.RunWorkerCompleted
executed on the UI main thread, or in a separate thread? Or asked diff开发者_如何学运维erently: do I have to embed my code inusing(NSAutoReleasePool)
and do I have toInvokeOnMainThread()
like would have to when using a normal thread? - Do I have to use
NSAutoReleasePool
inside theBackgroundWorker.DoWork
delegate?
BackgroundComponentWorker has not been adapted to work on MonoTouch or Mono for Android, so it does not do anything special with the UI thread.
Any of the events raised are not raised on the UI thread so you need to manually wrap those in BeginInvokeOnMainThread.
Is BackgroundWorker.RunWorkerCompleted executed on the UI main thread, or in a separate thread? Or asked differently: do I have to embed my code in using(NSAutoReleasePool) and do I have to InvokeOnMainThread() like would have to when using a normal thread?
BackgroundWorker.RunWorkerCompleted runs on the UI thread, provided the worker was created on that UI thread and you called RunWorkerAsync on the UI thread.
More precisely, BackgroundWorker uses SynchronizationContext.Current to run code on the UI thread. WPF, Silverlight, WinForms, Asp.NET all install a SynchronizationContext (e.g. System.Windows.Forms.WindowsFormsSynchronizationContext) when they're initialized.
Provided your UI framework is a good .NET citizen, it will install its own sync context, and BackgroundWorker will raise events on the UI thread.
Do I have to use NSAutoReleasePool inside the BackgroundWorker.DoWork delegate?
I can tell you that DoWork runs on a background thread. You'll need to play by the rules of your UI framework if you want to manipulate UI elements on that background thread.
According to this thread in the Mono mailing list,
- You don't have to put a NSAutoreleasePool in the DoWork handler unless you are manipulating Cocoa classes
- You HAVE to put a NSAutoreleasePool in the ProgressChanged handler to avoid memory leak. Seems like the running thread is not the main one.
- You HAVE to put a NSAutoreleasePool in the RunWorkerCompleted handler to avoid memory leak. Seems like the running thread is not the main one.
- You can modifiy directly label or progress indicator values on the handler, although they are not run on the main thread (read: dangerous). The best is to use the InvokeRequired flag and Invoke method to avoid cross-thread problems.
精彩评论