2012-06-18 14 views
14

¿Puedo definir un trabajador de fondo en un método?¿Trabajador de fondo y recolección de basura?

private void DownLoadFile(string fileLocation){ 
    BackgroundWorker worker = new BackgroundWorker(); 

    worker.DoWork += new DoWorkEventHandler((obj, args) => { 
     // Will be executed by back ground thread asynchronously. 
     args.Result = Download(fileLocation); 
    }); 

    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler((obj, args) => { 
     // will be executed in the main thread. 
     Result r = args.Result as Result; 
     ReportResult(r); 
    }); 

    worker.RunWorkerAsync(fileLocation); 
} 

Pregunta: Si Función de descarga() toma un largo tiempo para descargar el archivo, se puede poner en GC y la recogida de objetos antes de que el trabajador RunWorkerCompleted() se ejecuta?

+0

Recomendaría usar un delegado (Acción (de cadena)) y luego llamar a BeginInvoke. No veo ninguna necesidad de BackgroundWorker en este código. Todavía puede adjuntar un evento para cuando el método esté hecho. – JDB

+1

Una forma mejor de hacerlo sería agregarlo a la cola del grupo de subprocesos mediante 'QueueUserWorkItem': http://msdn.microsoft.com/en-us/library/system.threading.threadpool.queueuserworkitem.aspx –

+0

@J ... El subproceso de subprocesos es agradable, pero hace que el manejo de la devolución de llamada * a la derecha SynchronizationContext * sea más difícil. Sin embargo, el TPL lo maneja muy bien. –

Respuesta

12

Teniendo en cuenta que usted no está realmente utilizando gran parte de la funcionalidad de BackgroundWorker, yo recomendaría usar el TPL para este lugar:

private void DownLoadFile(string fileLocation) 
{ 
    Task.Factory.StartNew(() => Download(fileLocation)) 
     .ContinueWith(t => ReportResult(t.Result), TaskScheduler.FromCurrentSynchronizationContext()); 
} 

Dicho esto, el objeto worker no será de basura una vez que se está ejecutando, ya que el hilo de ThreadPool en sí mismo mantendrá al trabajador como un "objeto usado". El recolector de elementos no utilizados no podrá recopilarlo hasta después de que se ejecute el controlador de eventos de finalización, momento en el que no habría código de usuario que pudiera llegar a la instancia de BackgroundWorker.

Además, probablemente evitará que la instancia de esta clase sea recogida de basura, ya que los métodos de instancia (ReportResults) utilizados por el cierre mantienen la instancia de "esto" accesible y no elegible para GC.

+0

Esto no es realmente una respuesta a la pregunta del OP. Aún así un buen consejo. – JDB

+1

@ Cyborgx37 Agregó una respuesta directa a la pregunta del OP. –

+0

¿Realmente es una buena idea dejar que una variable como esa salga fuera del alcance? El programador que venga después de él esperará ver una variable en el ámbito que se hace referencia, no una variable zombie que está en el éter en alguna parte. –