Estoy tratando de agregarle un contador a una copia
Hola. El problema que has planteado carece de la información necesaria, para empezar la sentencia del For está incompleta / no es compilable. Intenta ser más específico la próxima vez y al menos aportar un código/ejemplo funcional... no nos hagas asumir las cosas, esto es programación y requiere todos los detalles posibles por tu parte para evitar asunciones y preguntas recurrentes.
se me actualice sin la necesidad de actualizar el form.
Lo que ocurre es que estás realizando una operación "bloqueante" en el thread de la UI, es decir, estás ejecutando un búcle en el thread de la UI y hasta que el bloque del For no termine su ejecuión no podrás hacer nada más. Aparte de eso, refrescar el Form por completo es una operación expensiva y no hay necesidad de ello, en todo caso deberías refescar el Label/Control en el que necesites actualizar "X" información llamando al método
Control.Update().
Con respecto al problema del bloqueo de la UI, la solución apropiada para llevar a cabo esto no es "hacer click y listo", se necesita un previo entendimiento y práctica por tu parte sobre la programación asincrónica en general. De todas formas te mostraré un ejemplo que puedes adaptar donde además te muestro el uso del paralelismo para acelerar la operación de copiado de archivos (o no. Depende, mientras no sean archivos de gran tamaño ok)...
En fin, lo que hace el siguiente código, aparte de evitar el bloqueo de la UI claro está, es realizar una copia NO-recursiva de los archivos del directorio "A" al directorio "B", y mostrar el progreso de archivos copiados en el control que le pasemos a la función, en este caso un label.
Imports System.IO
Imports System.Threading
Public NotInheritable Class Form1 : Inherits Form
Private Async Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
Dim copyTask As Task(Of Integer) = Me.CopyFiles("C:\Source\", "C:\Destination\", Me.Label1)
Await Task.WhenAll(copyTask)
MessageBox.Show(String.Format("Files copied: {0}", copyTask.Result))
End Sub
Public Async Function CopyFiles(ByVal srcDirPath As String, ByVal dstDirPath As String, ByVal progressCtrl As Control) As Task(Of Integer)
Dim files As IEnumerable
(Of FileInfo
) = New DirectoryInfo
(srcDirPath
).
EnumerateFiles("*", SearchOption.
TopDirectoryOnly) Dim maxFileCount
As Integer = files.
Count() Dim curFileCount As Integer
Dim updateLabelCallback As New SendOrPostCallback(
Sub(ByVal state As Object)
progressCtrl.Text = String.Format("{0} of {1} files copied...", CInt(state), maxFileCount)
End Sub)
Dim copySingleFileAction As New Action(Of FileInfo)(
Sub(ByVal file As FileInfo
) Try
file.
CopyTo(Path.
Combine(dstDirPath,
file.
Name), overwrite:
=True) SynchronizationContext.Current.Post(updateLabelCallback, Interlocked.Increment(curFileCount))
Catch ex As Exception
End Try
End Sub)
Dim copyAllFilesFunc As Func(Of Integer) =
Function() As Integer
Parallel.
ForEach(Of FileInfo
)(files, copySingleFileAction
) Return curFileCount ' Return the amount of files copied.
End Function
If Not New DirectoryInfo(dstDirPath).Exists Then
Directory.CreateDirectory(dstDirPath, Nothing)
End If
Dim t As New Task(Of Integer)(copyAllFilesFunc, TaskCreationOptions.LongRunning)
t.Start()
Await t
Return t.Result
End Function
End Class
Si por el momento este tipo de solución asincrónica te resultase incomprensible, entonces siempre puedes recurrir a llamar al método
Application.DoEvents() en el For que has compartido al principio, y listo, pero te advierto que hacer eso es programación irresponsable y deberías evitarlo a toda costa por varios motivos que no viene al caso explicar ahora (a menos que tengas esa duda).
Ejemplo:
Dim counter As Integer
for ...
File.
Copy(RutaOrigen, RutaGF, overwrite:
=True) FCopy.Text = CStr(Threading.Thread.Interlocked.Increment(counter))
' Descomentar en caso de que el valor no se actualice correctamente:
' FCopy.Update()
Application.DoEvents()
next
Saludos!