Pregunta

Quiero comenzar un trabajo en un nuevo hilo o usar backgroundworker para hacerlo, pero no lo he hecho antes y te pregunto de qué manera debo hacerlo.

Mi programa tiene una vista de cuadrícula de datos con una lista de archivos, un archivo por fila. Quiero que el usuario pueda seleccionar una fila y luego presione " Iniciar descarga " para iniciar un trabajo en segundo plano de la descarga. Quiero recuperar los eventos del progreso de la descarga.

Tengo una clase clsDownload que maneja todo y vuelve a generar eventos, pero ¿cómo implemento el trabajo en segundo plano?

¿Debo usar System.ComponentModel.BackgroundWorker dentro de la clase o crear algún contenedor que maneje esto o usar algún otro material de subprocesamiento?

Gracias.

Editar: No entiendo cómo implementar mi descarga en el backgroundworker, cualquier pequeño ejemplo sería muy bueno. El ejemplo en msdn no me llevó lejos.

Tengo una clase de descarga que tiene una función StartDownload. ¿Debo usar el trabajador de fondo EN la clase o en la persona que llama? " sentirse estúpido "

¿Fue útil?

Solución

He creado varias clases diferentes que incorporan BackgroundWorker. Lo que generalmente hago es tener un componente BackgroundWorker en el formulario que se abrirá cuando se realice el trabajo, luego paso esa instancia al constructor de mi clase de trabajo.

Así es como se vería su clase de trabajo:

Private m_bwMain As BackgroundWorker

Public Sub New(ByVal bwMain As BackgroundWorker)
    m_bwMain = bwMain

    'additional setup code here
End Sub

Para iniciar un trabajo, haría algo como esto en el controlador de eventos de clic de su botón Iniciar descarga:

lblStatus.Text = "Initializing ..."
bgwMain.RunWorkerAsync(someFileName)

Declaro mi clase de trabajo como miembro privado del formulario actual, y luego lo instancia en el evento BackgroundWorker.DoWork. Desde allí puede llamar a su método para descargar un archivo:

Private Sub bgwMain_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles bgwMain.DoWork
    m_oJobEngine = New JobEngine(CType(sender, BackgroundWorker))
    m_oJobEngine.DownloadFile(CStr(e.Argument))
End Sub

Para informar el progreso al usuario, puede manejar los eventos generados por su clase en su formulario principal. Solo necesita asegurarse de que la declaración del objeto de clase de trabajo tenga la palabra clave WithEvents. Desde esos controladores puede llamar al método ReportProgress de BackgroundWorker. Desde ReportProgress puede realizar los cambios que necesite en la interfaz de usuario para indicar el progreso. Aquí hay un ejemplo:

Private Sub m_oJobEngine.DownloadProgress(ByVal bgw as Backgroundworker, ByVal bytesTransferred as Long) Handles m_oJobEngine.DownloadProgress
    bgw.ReportProgress(0, bytesTransferred)
End Sub
Private Sub bgwMain_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles bgwMain.ProgressChanged
    lblStatus.Text = CLng(e.UserState).ToString & " bytes transferred."
End Sub

Espero que esto ayude.

Otros consejos

Si solo va a realizar la descarga y no necesita otro procesamiento asíncrono, puede usar los métodos asíncronos de WebClient . Aunque como ya tienes tu propia clase, probablemente no sea una solución para ti.

De lo contrario, puede usar BackgroundWorker como usted mencionó. La página de MSDN tiene un ejemplo de cómo hacerlo.

EDITAR: El cuento es:

  • Crea el BackgroundWorker a partir de la persona que llama;
  • Cuando desee iniciar el trabajo en segundo plano, llame a BackgroundWorker.RunWorkerAsync ;
  • en el controlador de eventos DoWork usted hace el trabajo de fondo, en su caso, inicie su clase de descarga;
  • mientras realiza el trabajo en segundo plano, debe verificar de vez en cuando el CancelationPending ;
  • cuando desee informar de algún progreso, debe calcularlo en porcentaje y llamar a ReportProgress .

Y si necesita algo realmente personalizado, siempre puede crear su propio Tema .

Personalmente me quedaría con BackgroundWorker . Tiene un buen conjunto de notificaciones para varias etapas del trabajo. Si utiliza Thread , tendrá que implementarlos usted mismo.

También me aseguraría de que el código no cree demasiadas instancias. Desea limitar el número de descargas precisas y poner en cola cualquier cosa que supere ese número.

Recomiendo encarecidamente a BackgroundWorker si necesita proporcionar comentarios al usuario sobre la interfaz de usuario. Los eventos ProgressChanged y RunWorkerCompleted se ejecutan en el subproceso de la interfaz de usuario, por lo que no es necesario realizar una clasificación, lo que puede hacer que su código sea más complejo.

El trabajador de fondo parece que debería funcionar ... Hay un ejemplo en MSDN.

http://msdn.microsoft.com/en -us / library / system.componentmodel.backgroundworker.aspx

O podrías hacer algo como:

WaitCallBack workCallBack= new WaitCallBack(DownloadMethod);
if(!ThreadPool.QueueUserWorkItem(workCallBack, "ThreadPooled")
{
   // Unable to Pool
}

// Work has been added to pool and will execute when possible

Depende de los parámetros que necesite para el subproceso.

La clase que usa clsDownload (probablemente su clase Form) debería usar BackgroundWorker para ejecutar el método de descarga.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top