elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Introducción a Git (Primera Parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  .NET (C#, VB.NET, ASP) (Moderador: kub0x)
| | | |-+  Ayuda con un Contador
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Ayuda con un Contador  (Leído 2,603 veces)
Tomas1982

Desconectado Desconectado

Mensajes: 48



Ver Perfil
Ayuda con un Contador
« en: 26 Enero 2017, 16:00 pm »

Estoy tratando de agregarle un contador a una copia, pero no e logrado de que este se me actualice sin la necesidad de actualizar el form. Esto es lo que tengo.

Código
  1. for
  2. File.Copy(RutaOrigen, RutaGF, True)
  3. FCopy.Text = "1" + Val(FCopy.Text)
  4. Me.Text = ListBox1.Items.Count.ToString() & ".Archivos"
  5. Me.Refresh()
  6. next
  7.  
 

Al refrescar me parpadea el form.
La idea es que este me enumere la cantidad de ficheros copiados.
Saludos y gracias.


« Última modificación: 31 Enero 2017, 21:08 pm por Tomas1982 » En línea

Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.885



Ver Perfil
Re: Ayuda con un Contador
« Respuesta #1 en: 28 Enero 2017, 20:44 pm »

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.

Código
  1. Imports System.IO
  2. Imports System.Threading
  3.  
  4. Public NotInheritable Class Form1 : Inherits Form
  5.  
  6.    Private Async Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
  7.        Dim copyTask As Task(Of Integer) = Me.CopyFiles("C:\Source\", "C:\Destination\", Me.Label1)
  8.        Await Task.WhenAll(copyTask)
  9.  
  10.        MessageBox.Show(String.Format("Files copied: {0}", copyTask.Result))
  11.    End Sub
  12.  
  13.    Public Async Function CopyFiles(ByVal srcDirPath As String, ByVal dstDirPath As String, ByVal progressCtrl As Control) As Task(Of Integer)
  14.  
  15.        Dim files As IEnumerable(Of FileInfo) = New DirectoryInfo(srcDirPath).EnumerateFiles("*", SearchOption.TopDirectoryOnly)
  16.        Dim maxFileCount As Integer = files.Count()
  17.        Dim curFileCount As Integer
  18.  
  19.        Dim updateLabelCallback As New SendOrPostCallback(
  20.            Sub(ByVal state As Object)
  21.                progressCtrl.Text = String.Format("{0} of {1} files copied...", CInt(state), maxFileCount)
  22.            End Sub)
  23.  
  24.        Dim copySingleFileAction As New Action(Of FileInfo)(
  25.            Sub(ByVal file As FileInfo)
  26.                Try
  27.                    file.CopyTo(Path.Combine(dstDirPath, file.Name), overwrite:=True)
  28.                    SynchronizationContext.Current.Post(updateLabelCallback, Interlocked.Increment(curFileCount))
  29.                Catch ex As Exception
  30.                End Try
  31.            End Sub)
  32.  
  33.        Dim copyAllFilesFunc As Func(Of Integer) =
  34.            Function() As Integer
  35.                Parallel.ForEach(Of FileInfo)(files, copySingleFileAction)
  36.                Return curFileCount ' Return the amount of files copied.
  37.            End Function
  38.  
  39.        If Not New DirectoryInfo(dstDirPath).Exists Then
  40.            Directory.CreateDirectory(dstDirPath, Nothing)
  41.        End If
  42.  
  43.        Dim t As New Task(Of Integer)(copyAllFilesFunc, TaskCreationOptions.LongRunning)
  44.        t.Start()
  45.        Await t
  46.  
  47.        Return t.Result
  48.    End Function
  49.  
  50. 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:
Código
  1. Dim counter As Integer
  2.  
  3. for ...
  4.    File.Copy(RutaOrigen, RutaGF, overwrite:=True)
  5.    FCopy.Text = CStr(Threading.Thread.Interlocked.Increment(counter))
  6.    ' Descomentar en caso de que el valor no se actualice correctamente:
  7.    ' FCopy.Update()
  8.    Application.DoEvents()
  9. next

Saludos!


« Última modificación: 29 Enero 2017, 18:07 pm por Eleкtro » En línea



Tomas1982

Desconectado Desconectado

Mensajes: 48



Ver Perfil
Re: Ayuda con un Contador
« Respuesta #2 en: 31 Enero 2017, 20:06 pm »

Eleкtro: Evidentemente ese no es el código, simplemente quise poner una idea de lo que quería, como lo explique. El código completo donde realizo la copia es este.

Código
  1.  
  2. Private Sub Organizar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Organizar.Click
  3.  
  4.        If TextBox1.Text = "" Then
  5.            MessageBox.Show("Seleccionar ruta origen", "Ruta...")
  6.        ElseIf TextBoxDestino.Text = "" Then
  7.            MessageBox.Show("Seleccione ruta Destino", "Ruta...")
  8.        End If
  9.        'Recorre el Listbox item por item
  10.        Try
  11.            For i As Integer = 0 To Me.ListBox1.Items.Count - 1
  12.                RutaOrigen = ListBox1.Items(i)
  13.                'Obtener el nombre del fichero
  14.                NDFichero = Path.GetFileName(RutaOrigen)
  15.                'Obtener la extensión del fichero
  16.                ExtFichero = Path.GetExtension(RutaOrigen)
  17.                'Le quito el punto para usarlo en el nombre de la carpeta
  18.                Dim MyChar() As Char = {"."}
  19.                NCConExt = ExtFichero.TrimStart(MyChar)
  20.                Console.WriteLine(NCConExt)
  21.                'Crea el directorio si no existe
  22.                If Not Directory.Exists(RutaDestino & "\" & NCConExt & "\") Then
  23.                    Directory.CreateDirectory(RutaDestino & "\" & NCConExt & "\")
  24.                End If
  25.                'Prepara la ruta mas el fichero a copiar
  26.                RDestino = RutaDestino & "\" & NCConExt & "\" & ExtFichero
  27.                'Try
  28.  
  29.                If System.IO.File.Exists(RDestino) Then
  30.                    '<<El archivo a copiar ya existe en destino>>
  31.                    'Obtiene nombre del archivo sin extensión
  32.                    Dim sFileName As String = ExtFichero.Substring(0, ExtFichero.Length - ExtFichero.ToString.Length)
  33.                    Dim num As Integer = Nothing
  34.                    While System.IO.File.Exists(RDestino) 'Cambia el
  35.                        num += 1
  36.                        'Renombra archivo en destino. Ej: C:\Organizado\ext\file(1).ext
  37.                        RDestino = String.Format("{0}{1}({2}){3}", RutaDestino & "\" & NCConExt & "\", sFileName, num, ExtFichero)
  38.                    End While
  39.                End If
  40.                Try
  41.                    If RadioButton1.Checked = True Then
  42.                        File.Copy(CStr(RutaOrigen), RDestino, False)
  43.                    Else
  44.                        File.Move(CStr(RutaOrigen), RDestino)
  45.                    End If
  46.                    'Muestra el fichero que se esta copiando
  47.                    RutDFichero.Text = RutaOrigen
  48.                    RutDFichero.Update()
  49.                Catch ex As Exception
  50.                    MsgBox("Error: " & ex.Message)
  51.                End Try
  52.                FCopy.Text = "1" + Val(FCopy.Text)
  53.                FCopy.Update()
  54.            Next
  55.        Catch ex As Exception
  56.            MsgBox("No se realizó la operación por: " & ex.Message)
  57.        End Try
  58.        Dim result As Integer = MessageBox.Show("Operación terminada> Deseas limpiar los datos", "caption", MessageBoxButtons.YesNo)
  59.        If result = DialogResult.No Then
  60.            Exit Sub
  61.        ElseIf result = DialogResult.Yes Then
  62.            Limpiardatos()
  63.        End If
  64.    End Sub
  65.  
  66.  
   

Darle una revisada para ver que me va mal y corregirlo. Saludossss
En línea

Eleкtro
Ex-Staff
*
Desconectado Desconectado

Mensajes: 9.885



Ver Perfil
Re: Ayuda con un Contador
« Respuesta #3 en: 1 Febrero 2017, 00:02 am »

Darle una revisada para ver que me va mal y corregirlo.

Hola.

Aquí no se aceptan órdenes, ni tampoco le hacemos el trabajo a nadie.



Debo comentar algo, y es que ha habido una pequeña confusión. La primera vez que leí tu post donde explicaste el problema, por algún motivo me rallé (lo lei deprisa o algo, no se) y pensé que te referias a un problema de bloqueo de la UI, no a un problema de flickering, y te mostré dos soluciones diferentes enfocadas a evitar el bloqueo de la UI (que no el flickering), lo siento por eso. Lo bueno de esto es que de todas formas puedes aprovechar el primer ejemplo (el asincrónico) para adaptarlo y evitar llamar a "Me.Refresh()" ya que refrescar el Form/Todos los controles es el causante de lo que te ocurre. Empieza por leer a fondo la respuesta que te di donde digo que debes hacer en lugar de llamar a "Me.Refresh", y adaptar a tus necesidades aquél que mostré código. Ah, y para reducir (o en el mejor de los casos evitar) el flickering en WindowsForms siempre es bueno que actives la propiedad DoubleBuffered de tu Form.

Saludos.
« Última modificación: 1 Febrero 2017, 00:05 am por Eleкtro » En línea



Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Ayuda con codigo en C, contador
Programación C/C++
PurpleSixx 0 2,019 Último mensaje 29 Marzo 2012, 08:29 am
por PurpleSixx
AYUDA!!!! : Contador de variables!!! URGENTE
Desarrollo Web
Puntoinfinito 6 3,616 Último mensaje 24 Octubre 2012, 23:39 pm
por Puntoinfinito
Ayuda para un contador
Programación C/C++
MGMR 4 2,391 Último mensaje 17 Abril 2015, 03:41 am
por Gunhack
contador de palabras (ayuda con el error)
Programación C/C++
creiko 3 2,522 Último mensaje 3 Septiembre 2016, 00:46 am
por JonaLamper
Ayuda. Forkbomb con contador de procesos
Scripting
pepinoise 1 2,611 Último mensaje 9 Septiembre 2020, 21:43 pm
por crazykenny
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines