Mit .NET brachte Microsoft den heiligen Gral des Mutlithreadings zu den VB Programmierern. Bis dahin mußten wir uns mit DoEvents vor UI Lockups bewahren, oder noch schlimmer Out Of Process ActiveX-Exen programmieren um diese zu verhinden. Programmieren mit Threads bringt jedoch neue Probleme mit sich wie Deadlocks, nicht mehr ansprechbare Controls da diese in einem anderen Thread laufen usw. Dieses kleine VB.NET 2005 Beispiel sollte einen kleinen übersichtlichen Einstieg in das Programmieren mit dem Backgroundworkerthread bieten. Das Beispiel sollte eine große Datei byteweise in einem eigenen Thread kopieren und dabei einen Progress darstellen. Die Operation sollte natürlich jederzeit abbrechbar sein. Dazu legen wir ein neues Windowsformsprojekt an und legen folgende Controls auf Form1:
Nun zum Code: Imports System.IO Imports System.ComponentModel Private Variablen: ' unser Thread Private th As BackgroundWorker ' wieviele Bytes wurden kopiert Private lngBytesCopied As Long ' Die Speicheradresse der Zieldatei Private lngSourceFileLength As Long Die Ladeprozedur des Formulares: Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load th = New BackgroundWorker AddHandler th.DoWork, AddressOf th_DoWork AddHandler th.RunWorkerCompleted, AddressOf th_Completed AddHandler th.ProgressChanged, AddressOf th_ProgressChanged th.WorkerReportsProgress = True th.WorkerSupportsCancellation = True Me.lblSource.Text = "<Source File>" Me.lblTarget.Text = "<Target File>" Me.cmdCopyAsync.Enabled = False Me.cmdCancel.Enabled = False Me.progress.Visible = False Me.lblProgress.Visible = False End Sub Die Routinen für das Auswählen der Source und Zieldatei. Eigentlich selbsterklärend. Private Sub cmdSelectSource_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles cmdSelectSource.Click Dim openDlg As New OpenFileDialog With openDlg .Title = "Select file" .InitialDirectory = Application.StartupPath If .ShowDialog = Windows.Forms.DialogResult.OK Then Me.lblSource.Text = .FileName End If End With End Sub Private Sub cmdSelectTarget_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles cmdSelectTarget.Click Dim fldBrowser As New FolderBrowserDialog With fldBrowser .ShowNewFolderButton = True If .ShowDialog = Windows.Forms.DialogResult.OK Then Me.lblTarget.Text = .SelectedPath Me.cmdCopyAsync.Enabled = True End If End With End Sub Hier wird der asnchrone Thread gestartet: Private Sub cmdCopyAsync_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles cmdCopyAsync.Click If Me.lblTarget.Text.Length > 0 And Me.lblSource.Text.Length > 0 Then Me.cmdCopyAsync.Enabled = False Me.progress.Minimum = 0 Me.progress.Maximum = 100 Me.progress.Visible = True Me.lblProgress.Visible = True Me.cmdCancel.Enabled = True ' Start des Threads löst dann die th_DoWork Prozedur aus th.RunWorkerAsync() End If End Sub So jetzt das eigentliche Arbeitspferd, die th_DoWork Prozedur kopiert die Datei in einem eigenen Thread. Private Sub th_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Dim fi As New FileInfo(Me.lblSource.Text) Dim inStream As FileStream = Nothing Dim outStream As FileStream = Nothing Dim buffer(2048) As Byte Dim offset As Integer = 0 Try inStream = New FileStream(fi.FullName, FileMode.Open) outStream = New FileStream(Me.lblTarget.Text & "\" & fi.Name, FileMode.Create) lngSourceFileLength = inStream.Length Do If th.CancellationPending = True Then e.Cancel = True inStream.Close() outStream.Close() Exit Sub End If offset = inStream.Read(buffer, 0, buffer.Length) outStream.Write(buffer, 0, offset) lngBytesCopied += offset ' WICHTIG: Hier könen wir einen Progress darstellen th.ReportProgress(offset / inStream.Length * 100) Loop Until offset = 0 Catch ex As Exception MessageBox.Show(ex.Message) Finally inStream.Close() outStream.Close() End Try End Sub Jetzt stellen wir den Progress dar. Private Sub th_ProgressChanged(ByVal sender As Object, _ ByVal e As ProgressChangedEventArgs) Try Me.lblProgress.Text = lngBytesCopied.ToString & " Bytes From " & _ lngSourceFileLength.ToString & " Copied" Me.progress.Value = e.ProgressPercentage.ToString Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub Die Cancel-Operation: Private Sub cmdCancel_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles cmdCancel.Click If th.IsBusy Then th.CancelAsync() End If End Sub Wenn der Thread abgeschlossen ist werden wir in der th_completed inklusive Status davon benachrichtigt. Private Sub th_Completed(ByVal sender As Object, _ ByVal e As RunWorkerCompletedEventArgs) Dim strFinished As String = String.Empty If e.Cancelled Then strFinished = "Operation Cancelled" ElseIf e.Error IsNot Nothing Then strFinished = "Operation Error " & e.Error.Message Else strFinished = "Operation Sucessfull" End If MessageBox.Show("CopyThread finished" & vbCrLf & strFinished) Me.cmdCopyAsync.Enabled = True End Sub Noch eine schnelle Sicherheitsüberprüfung, ob der Thread nicht rennt, wenn das Form geschlossen wird. Private Sub Form1_FormClosing(ByVal sender As Object, _ ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing If th.IsBusy Then th.CancelAsync() End If End Sub Man kann das Weiterlaufen der UI schön beobachten, indem man einfach während der Copy-Operation einen Text in die Textbox "txtTest" eingibt. Dieser Tipp wurde bereits 38.172 mal aufgerufen. Voriger Tipp | Zufälliger Tipp | Nächster Tipp
Anzeige
Diesen und auch alle anderen Tipps & Tricks finden Sie auch auf unserer aktuellen vb@rchiv Vol.6 (einschl. Beispielprojekt!) Ein absolutes Muss - Geballtes Wissen aus mehr als 8 Jahren vb@rchiv! - nahezu alle Tipps & Tricks und Workshops mit Beispielprojekten - Symbol-Galerie mit mehr als 3.200 Icons im modernen Look Weitere Infos - 4 Entwickler-Vollversionen (u.a. sevFTP für .NET), Online-Update-Funktion u.v.m. |
sevISDN 1.0 Überwachung aller eingehender Anrufe! Die DLL erkennt alle über die CAPI-Schnittstelle eingehenden Anrufe und teilt Ihnen sogar mit, aus welchem Ortsbereich der Anruf stammt. Weitere Highlights: Online-Rufident, Erkennung der Anrufbehandlung u.v.m. Tipp des Monats Mai 2024 Hermann Röttger Wochentage eines Datumsbereichs ermitteln Wochentage eines Datumsbereichs ermitteln, optional mit Feiertagsberechnung Neu! sevEingabe 3.0 Einfach stark! Ein einziges Eingabe-Control für alle benötigten Eingabetypen und -formate, inkl. Kalender-, Taschenrechner und Floskelfunktion, mehrspaltige ComboBox mit DB-Anbindung, ImageComboBox u.v.m. |
||||||||||||||||
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein. |