1

I'm trying to create an app to copy massive amounts of files in vb.net and I'm trying to make it asynchronous, so I can pause, stop and create a counter over the progress bars, and I have researched a little bit on how to do it, but I don't quite understand how to modify my code.

This is most of the code I'm working on:

Private Sub btnMoverImagenes_Click(sender As Object, e As EventArgs) Handles btnMoverImagenes.Click
    Dim carpetaProducto As String
    Dim agno As String
    Dim mes As String
    Dim dia As String
    Dim secuencia As String
    Dim rutaOrigen As String
    Dim RutaDestinoOp As String
    Dim RutaDestinoHis As String
    Dim archivo As String
    Dim DestinoArchivoOrigen As String
    Dim DestinoArchivoHistorico As String
    Dim idregistro As Integer
    Dim dsregistros As Integer
    Dim imagenMulti As String
    Dim nuevaRutaImagenMulti As String
    Dim nombreImagenOrigen As String
    Dim contadorIMGCopiadas As Integer = 0
    Dim contadorRegistros As Integer = 0
    Dim contadorArchivosSinImagen As Integer = 0
    Dim h1 As Date
    Dim h2 As Date
    Dim tiempoCarga As String
    Dim fechaCarga As String
    h1 = System.DateTime.Now
    ProgressBar1.Minimum = 0
    ProgressBar1.Maximum = 1000
    ProgressBar1.Value = 0
    ProgressBar2.Minimum = 0
    ProgressBar2.Maximum = 1000
    ProgressBar2.Value = 0
    fechaDesde = dtpDesde.ToString
    fechaHasta = dtpHasta.ToString
    dtpDesde.Format = DateTimePickerFormat.Custom
    dtpDesde.CustomFormat = "yyyyMMdd"
    fechaDesde = dtpDesde.Text
    dtpHasta.Format = DateTimePickerFormat.Custom
    dtpHasta.CustomFormat = "yyyyMMdd"
    fechaHasta = dtpHasta.Text
    dsImagenes = EjecutarXML(conexionDat, fechaDesde, fechaHasta)
    Try
        If dsImagenes.Tables(dsImagenes.Tables.Count - 1).Rows(0).Item(3) > 0 Then
            dsregistros = dsImagenes.Tables(0).Rows.Count
            ProgressBar1.Minimum = 0
            ProgressBar1.Maximum = dsregistros
            ProgressBar1.Value = 0
            ProgressBar2.Minimum = 0
            ProgressBar2.Maximum = dsregistros
            ProgressBar2.Value = 0
            Label5.Text = ProgressBar1.Value.ToString + " de " + ProgressBar1.Maximum.ToString
            Label6.Text = ProgressBar2.Value.ToString + " de " + ProgressBar2.Maximum.ToString
            Log("******* SE INICIA CARGA *******")
            If dsImagenes.Tables(0).Rows.Count > 0 Then
                For Each row As DataRow In dsImagenes.Tables(0).Rows
                    archivo = row.Item(0).ToString()
                    carpetaProducto = row.Item(3).ToString()
                    rutaOrigen = row.Item(1).ToString()
                    idregistro = row.Item(2).ToString()
                    agno = row.Item(4).ToString()
                    mes = row.Item(5).ToString()
                    dia = row.Item(6).ToString()
                    secuencia = row.Item(7).ToString()
                    fechaCarga = row.Item(9).ToString()
                    imagenMulti = row.Item(8).ToString()
                    nombreImagenOrigen = row.Item(10).ToString()
                    nuevaRutaImagenMulti = carpetaProducto + "\" + agno + "\" + mes + "\" + dia + "\" + secuencia + "\" + nombreImagenOrigen
                    RutaDestinoOp = RutaDestinoNasOp + "\" + carpetaProducto + "\" + agno + "\" + mes + "\" + dia + "\" + secuencia
                    RutaDestinoHis = RutaDestinoNasHis + "\" + carpetaProducto + "\" + agno + "\" + mes + "\" + dia + "\" + secuenciavo
                    DestinoArchivoOrigen = RutaDestinoNasOp + "\" + carpetaProducto + "\" + agno + "\" + mes + "\" + dia + "\" + secuencia + "\" + nombreImagenOrigen
                    DestinoArchivoHistorico = RutaDestinoNasHis + "\" + carpetaProducto + "\" + agno + "\" + mes + "\" + dia + "\" + secuencia + "\" + archivo
                    Log("------------------------------------------------------------------------------")
                    Log("******* Inicio copia archivo IDREGISTRO: " + idregistro.ToString + " *******")
                    If ValidaExisteImagenOrigen(rutaOrigen) = True Then
                        If ValidarRutaOrigen(rutaOrigen) = True Then
                            If CargaNasHistorico(rutaOrigen, RutaDestinoHis, DestinoArchivoHistorico, conexionDat, idregistro) = True Then
                                If CargaNasOperativo(rutaOrigen, RutaDestinoOp, DestinoArchivoOrigen, conexionDat, idregistro, nuevaRutaImagenMulti) = True Then
                                    contadorIMGCopiadas = contadorIMGCopiadas + 1
                                    If ProgressBar2.Value < ProgressBar2.Maximum Then
                                        ProgressBar2.Value += 1
                                    End If
                                End If
                            End If
                        Else
                            If ValidaImagenHistorico(DestinoArchivoHistorico) = True Then
                                If CargaNasHistorico(rutaOrigen, RutaDestinoHis, DestinoArchivoHistorico, conexionDat, idregistro) = True Then
                                    contadorIMGCopiadas = contadorIMGCopiadas + 1
                                    If ProgressBar2.Value < ProgressBar2.Maximum Then
                                        ProgressBar2.Value += 1
                                    End If
                                Else
                                    Log("******* TODO OK, Registro id: " + idregistro.ToString + ". no se realiza copia de imagen *******")
                                    contadorIMGCopiadas = contadorIMGCopiadas + 1
                                    If ProgressBar2.Value < ProgressBar2.Maximum Then
                                        ProgressBar2.Value += 1
                                    End If
                                End If
                            End If
                        End If
                    Else
                        Log("******* ALERTA: Registro id: " + idregistro.ToString + " NO EXISTE *******")
                        contadorArchivosSinImagen = contadorArchivosSinImagen + 1
                    End If
                    contadorRegistros = contadorRegistros + 1
                    Log("******* Finaliza copia archivo IDREGISTRO: " + idregistro.ToString + " *******")
                    archivo = ""
                    carpetaProducto = ""
                    rutaOrigen = ""
                    idregistro = 0
                    agno = ""
                    mes = ""
                    dia = ""
                    secuencia = ""
                    If ProgressBar1.Value < ProgressBar1.Maximum Then
                        ProgressBar1.Value += 1
                    End If
                    Label5.Text = ProgressBar1.Value.ToString
                    Label6.Text = ProgressBar2.Value.ToString + " de " + ProgressBar2.Maximum.ToString
                Next
                h2 = System.DateTime.Now
                tiempoCarga = (h2 - h1).ToString
                MsgBox("Proceso Terminado, revisar log para ver el detalle del proceso completo")
                Log("------------------------------------------------------------------------------")
                Log("******* Copia Finalizada, IMAGENES COPIADAS: " + contadorIMGCopiadas.ToString + " DE " + dsregistros.ToString + " *******")
                Log("******* REGISTROS SIN IMAGENES: " + contadorArchivosSinImagen.ToString + " *******")
                Log("******* TIEMPO DE EJECUCION: " + tiempoCarga + " *******")
            End If
        Else
            MsgBox("sin datos para la fecha seleccionada")
        End If

    Catch ex As Exception
        MsgBox("ocurrio un error al buscar los datos")
    End Try
End Sub

I'd really apreciate if someone could help me.

Throkar
  • 73
  • 3
  • 11
  • One thing that you are probably missing is a `DoEvents` before your `Next`. It will force a thread synchronization. Of course, this will slow things down a little, but it will force your UI to update and gives a chance to respond to other events like (pause/stop) button.click. – tgolisch Feb 27 '19 at 16:00
  • Btw, WinForms naturally runs on two threads: one for the foreground (UI draw/update) and a background thread. DoEvents simply interrupts the background thread and allows any other threads to take a turn, before continuing. If you really insist on running this code on another thread, you will have a bunch of work to set up delegates, so you can reach your UI controls from your background thread. It is interesting & fun, but WAAAAY more work than simply adding a DoEvents. – tgolisch Feb 27 '19 at 16:04
  • 1
    It should be noted that using `DoEvents()` as @tgolisch is not a solution but rather a bad workaround/hack _**and should not be used**_. `DoEvents()` processes all available messages in the message queue (one of those is `WM_PAINT`) which allows the form to redraw itself. It should be noted that while this technically makes the form responsive, it does so in a bad way as it will eat as much CPU as possible and make your code prone to unexpected errors. – Visual Vincent Feb 27 '19 at 16:38
  • For a more in-depth explanation I recommend reading [Keeping your UI Responsive and the Dangers of Application.DoEvents](https://blogs.msdn.microsoft.com/jfoscoding/2005/08/06/keeping-your-ui-responsive-and-the-dangers-of-application-doevents/). There's also a lot of Stack Overflow answers about it. – Visual Vincent Feb 27 '19 at 16:39
  • The correct way of performing background work is by using a `Thread` or a `Task` ([read more here](https://learn.microsoft.com/en-us/dotnet/standard/parallel-programming/task-based-asynchronous-programming)). As tgolish also mentioned, any time you want to update the user interface (UI) you would need to _delegate_ that work from the background thread to the UI thread. This is done using `Control.Invoke()`. I've written an answer about it here which covers the basics: [How can I run code in a background thread and still access the UI?](https://stackoverflow.com/a/45571728) – Visual Vincent Feb 27 '19 at 16:47
  • @tgolisch : _"It is interesting & fun, but WAAAAY more work than simply adding a DoEvents"_ - If you think invoking is too much work or takes too long time to do, you might also benefit from the answer I linked above. -- By the way, WinForms has only the UI thread by default, no (direct) background threads (that's up to the programmer). And `DoEvents()` _doesn't_ interrupt a _"background thread and allows any other threads to take a turn"_ - threads run in parallel. It merely forces the message pump to process all available messages which may or may not execute other event handlers. – Visual Vincent Feb 27 '19 at 17:00

0 Answers0