Domanda

Voglio iniziare un lavoro in un nuovo thread o usare backgroundworker per farlo, ma non l'ho mai fatto prima e chiedendoti in che modo dovrei farlo.

Il mio programma ha una vista dati con un elenco di file, un file per riga. Voglio che l'utente sia in grado di selezionare una riga e quindi premere " Avvia download " per avviare un processo in background del download. Voglio recuperare gli eventi sullo stato di avanzamento del download.

Ho un clsDownload di classe che gestisce tutto e genera eventi, ma come posso implementare il backgroundworking?

Dovrei usare System.ComponentModel.BackgroundWorker all'interno della classe o creare un wrapper che gestisca questo o usare altre cose di threading?

Grazie.

Modifica: Non capisco come implementare il mio download in backgroundworker, qualsiasi piccolo esempio sarebbe molto bello. L'esempio su msdn non mi ha portato lontano.

Ho una classe di download che ha una funzione StartDownload. Dovrei usare il backgroundworker IN nella classe o nel chiamante? " stupido "

È stato utile?

Soluzione

Ho creato diverse classi che incorporano BackgroundWorker. Quello che faccio generalmente è avere un componente BackgroundWorker sul modulo che sarà aperto quando il lavoro viene eseguito, quindi passo quell'istanza al costruttore della mia classe di lavoro.

Ecco come potrebbe apparire la tua classe di lavoro:

Private m_bwMain As BackgroundWorker

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

    'additional setup code here
End Sub

Per iniziare un lavoro, dovresti fare qualcosa del genere nel gestore di eventi Click del pulsante Avvia download:

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

Dichiaro la mia classe di lavoro come membro privato del modulo corrente, quindi istanzio nell'evento BackgroundWorker.DoWork. Da lì puoi chiamare il tuo metodo per scaricare un file:

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

Per segnalare all'utente i progressi, puoi gestire gli eventi generati dalla tua classe nel modulo principale. Devi solo assicurarti che la dichiarazione dell'oggetto classe di lavoro abbia la parola chiave WithEvents. Da quei gestori è possibile chiamare il metodo ReportProgress di BackgroundWorker. Da ReportProgress puoi apportare qualsiasi modifica necessaria all'interfaccia utente per indicare l'avanzamento. Ecco un esempio:

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

Spero che questo aiuti.

Altri suggerimenti

Se hai intenzione di scaricare e non ho bisogno di altre elaborazioni asincrone, puoi semplicemente usare i metodi asincroni di classe WebClient . Anche se dal momento che hai già la tua classe, probabilmente non è una soluzione per te.

Altrimenti, puoi utilizzare BackgroundWorker come hai detto. La pagina MSDN ha un esempio su come farlo.

EDIT: Il racconto è:

  • Crea il BackgroundWorker dal chiamante;
  • Quando vuoi iniziare il lavoro in background, chiami BackgroundWorker.RunWorkerAsync ;
  • nel gestore di eventi DoWork esegui il lavoro in background, nel tuo caso inizi la classe di download;
  • mentre lavori in background, devi controllare ogni tanto CancelationPending ;
  • quando vuoi segnalare alcuni progressi, devi calcolarlo in percentuale e chiamare ReportProgress .

E se hai bisogno di qualcosa di veramente personalizzato, puoi sempre creare il tuo Discussione .

Personalmente rimarrei con BackgroundWorker . Ha un bel set di notifiche per le varie fasi del lavoro. Se usi Thread , dovrai implementarli da soli.

Vorrei anche assicurarmi che il codice non crea troppe istanze. Vuoi limitare il numero di download simultanei e mettere in coda qualsiasi cosa oltre quel numero.

Consiglio vivamente BackgroundWorker se è necessario fornire un feedback all'utente sull'interfaccia utente. Gli eventi ProgressChanged e RunWorkerCompleted vengono eseguiti sul thread dell'interfaccia utente, quindi non è necessario eseguire il marshalling, il che può rendere il codice più complesso.

Sembra che il backgroundworker dovrebbe funzionare ... C'è un esempio su MSDN.

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

O potresti fare qualcosa del genere:

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

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

Dipende da quali parametri è necessario per il thread.

La classe che usa clsDownload (probabilmente la tua classe Form) dovrebbe usare BackgroundWorker per eseguire il metodo di download.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top