2009-03-05 15 views
4

Ich möchte einen Job in einem neuen Thread starten oder backgroundworker verwenden, aber ich habe das vorher noch nicht gemacht und frage dich, wie ich es machen soll.Laufende Klasse als neuer Thread

Mein Programm hat eine Datagridview mit einer Liste von Dateien, eine Datei pro Zeile. Ich möchte, dass der Benutzer eine Zeile auswählen kann und dann auf "Download starten" klicken, um einen Hintergrundjob des Downloads zu starten. Ich möchte Ereignisse vom Fortschritt des Downloads abrufen.

Ich habe eine Klasse clsDownload, die alles behandelt und löst Ereignisse zurück, aber wie implementiere ich die Hintergrundverarbeitung?

Sollte ich den System.ComponentModel.BackgroundWorker in der Klasse verwenden oder einen Wrapper erstellen, der das handhabt oder ein anderes Threading verwendet?

Danke.

Edit: Ich verstehe nicht, wie ich meinen Download im Hintergrundarbeiter implementieren, jedes kleine Beispiel wäre sehr nett. Das Beispiel auf msdn hat mich nicht weit gebracht.

Ich habe eine Download-Klasse, die eine StartDownload-Funktion hat. Soll ich den Hintergrundarbeiter IN der Klasse oder im Anrufer verwenden? "Gefühl dumm"

Antwort

1

Ich habe mehrere verschiedene Klassen erstellt, die Background integrieren. Was ich im Allgemeinen mache, ist eine BackgroundWorker-Komponente im Formular, die geöffnet wird, wenn der Job ausgeführt wird, und dann übergebe ich diese Instanz an den Konstruktor meiner Job-Klasse. Hier

ist, was Ihre Job-Klasse aussehen könnte:

Private m_bwMain As BackgroundWorker 

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

    'additional setup code here 
End Sub 

Um einen Job zu starten, würden Sie so etwas wie dies in den Click-Ereignishandler von Ihrer Start-Schaltfläche Download tun:

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

Ich deklariere meine Jobklasse als privates Mitglied des aktuellen Formulars und instanziiere sie dann im BackgroundWorker.DoWork-Ereignis. Von dort können Sie Ihre Methode aufrufen, eine Datei herunterzuladen:

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 

Um Fortschritte an den Benutzer zu melden, können Sie die Ereignisse von Ihrer Klasse in Ihrer Hauptform angehoben behandeln. Sie müssen nur sicherstellen, dass die Jobklassenobjektdeklaration das WithEvents-Schlüsselwort hat. Von diesen Handlern können Sie die ReportProgress-Methode von BackgroundWorker aufrufen. In ReportProgress können Sie alle erforderlichen Änderungen an der Benutzeroberfläche vornehmen, um den Fortschritt anzuzeigen. Hier ist ein Beispiel:

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 

Ich hoffe, dies hilft.

0

Der Hintergrundarbeiter sieht aus wie es sollte funktionieren ... Es gibt ein Beispiel auf MSDN.

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

Oder Sie könnten so etwas wie:

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

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

abhängig, welche Parameter falls vorhanden Sie für das Thema benötigen.

+0

würde ich gegen WaitCallback raten, da es schwieriger ist, Ereignisse an den UI-Thread zurückzukehren (die ich etwas davon ausgehen, ist er erreichen will). – Inferis

3

Ich werde nur herunterladen und brauche keine andere asynchrone Verarbeitung, Sie können nur die asynchronen Methoden der Klasse WebClient verwenden. Obwohl Sie bereits eine eigene Klasse haben, ist das wahrscheinlich keine Lösung für Sie.

Andernfalls können Sie BackgroundWorker verwenden, wie Sie erwähnt haben. Die MSDN-Seite hat ein Beispiel dafür.

EDIT: Die Kurzgeschichte ist:

  • Sie die BackgroundWorker vom Anrufer erstellen; Wenn Sie die Hintergrundarbeit starten möchten, rufen Sie BackgroundWorker.RunWorkerAsync;
  • in der DoWork Event-Handler Sie die Hintergrundarbeit, in Ihrem Fall starten Sie Ihre Download-Klasse;
  • Während Sie die Hintergrundarbeit machen, müssen Sie hin und wieder nach CancelationPending; Wenn Sie einen Fortschritt melden möchten, müssen Sie ihn in Prozent berechnen und ReportProgress anrufen.

Und wenn Sie etwas wirklich angepasstes benötigen, können Sie immer Ihre eigene Thread erstellen.

Ich persönlich würde mit BackgroundWorker bleiben. Es hat eine Reihe von Benachrichtigungen für verschiedene Phasen des Jobs.Wenn Sie Thread verwenden, müssen Sie diese selbst implementieren.

würde ich auch sicherstellen, dass der Code nicht zu viele Fälle nicht erstellen. Sie möchten die Anzahl der Downloads begrenzen und alles nach dieser Nummer in die Warteschlange stellen.

+0

Ich benutze Webservices und MTOM, um große Dateien von einem Server zu bekommen, so dass ich nicht mit dem WebClient kooperieren kann. – Stefan

+0

In diesem Fall generieren Sie asynchrone Methoden in Ihrer Dienstreferenz und verwenden diese. – Inferis

+0

@inferis - asynchrone Methoden auf dem Webservice werden keine Fortschrittsbenachrichtigungen bereitstellen. –

3

Ich würde stark BackgroundWorker beraten, wenn Sie Feedback an den Benutzer auf der Benutzeroberfläche zur Verfügung stellen müssen. Die ProgressChanged und RunWorkerCompleted Ereignisse werden auf dem UI-Thread ausgeführt werden, so gibt es keine Notwendigkeit Rangierung zu tun, die Ihren Code komplexer machen.

+0

Hi @ user927258, bitte vermeiden Sie kleinere Änderungen. Siehe: http://meta.stackexchange.com/questions/180545/mass-editing-existing-answers-with-a-similar-pattern – yannis

+0

@Inferis in Ordnung. – vasanth

0

Die Klasse, die clsDownload (wahrscheinlich die Form-Klasse) verwendet, sollte Background verwenden, um die Download-Methode auszuführen.

Verwandte Themen