Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Eleкtro

#3241
Ingeniería Inversa / Re: Apk código fuente
17 Septiembre 2016, 13:28 PM
#3242
Para resumir brevemente todas las explicaciones que di en el post de arriba, lo que debes hacer para solucionar este tipo de problemas es:
1. Manipular una imagen en miniatura de la imagen a tamaño real.
2. Ajustar los parámetros de calidad de GDI+ al manipular la imagen, para reducir la calidad del resultado (solo en la previsualización, claro).
3. Utilizar técnicas de multi-threading para evitar bloquear el thread de la UI con instrucciones o metodologías expensivas que resulten en congelamientos o "trompicones" al manejar la UI.

Y... en lo último que debes pensar al manipular gráficos en .NET es en recurrir a la API de Windows, los gráficos 2D/3D es una temática que requiere mucha experiencia profesional, no solo de gráficos en general, sino de los tipos de datos que maneja Windows (y la forma especial de utilizar cada uno y de liberar los recursos de cada uno), así que por muy cuidadoso que intentes ser siempre te vas a dejar alguna imperfección por el camino, y una imperfección utilizando código no administrado puede traernos serios problemas y ser muy dificil de localizar la raíz del problema, además, con la inmensa cantidad de miembros administrados que de por si ya expone la libreria de clases de .NET Framework para la manipulación de gráficos e imágenes, es que simplemente no es necesario usar la WinAPI.




He escrito el siguiente código para mostrarte como puedes corregir esos problemas, pero recuerda que esto también es solo un código de ejemplo (no me he esmerado como lo haría para un trabajo).
La matriz de color no la he cambiado, he dejado la misma que estabas usando tú.

Código (vbnet) [Seleccionar]
Imports System.Drawing.Drawing2D
Imports System.Drawing.Imaging

Public NotInheritable Class Form1 : Inherits Form

   Friend WithEvents PcbPreview As PictureBox
   Friend WithEvents BtLoad As Button
   Friend WithEvents BtSave As Button
   Friend WithEvents TrckHue As TrackBar
   Friend WithEvents LblHue As Label

   Private srcImg As Image
   Private thumbnail As Image

   Public Sub New()

       MyClass.InitializeComponent()

       Me.Size = New Size(520, 400)
       Me.DoubleBuffered = True

       Me.PcbPreview = New PictureBox With {
           .Location = New Point(10, 10),
           .Size = New Size(400, 240),
           .SizeMode = PictureBoxSizeMode.Normal,
           .BackColor = Color.DarkGray
       }

       Me.BtLoad = New Button With {
           .Location = New Point(Me.PcbPreview.Width + 20, 10),
           .Text = "Load from..."
       }

       Me.BtSave = New Button With {
           .Location = New Point(Me.PcbPreview.Width + 20, 40),
           .Text = "Save to..."
       }

       Me.TrckHue = New TrackBar With {
           .Location = New Point(10, Me.PcbPreview.Height + 20),
           .AutoSize = True,
           .Size = New Size(Me.PcbPreview.Width, 10),
           .TickStyle = TickStyle.TopLeft,
           .BackColor = Color.DarkGray,
           .TickFrequency = 50,
           .Maximum = 100,
           .Minimum = -100,
           .Value = 0,
           .Orientation = Orientation.Horizontal
       }

       Me.LblHue = New Label With {
           .Location = New Point(Me.TrckHue.Width + 20, Me.TrckHue.Top + 10),
           .AutoSize = True,
           .Text = "0",
           .Font = New Font("Arial", 20, FontStyle.Bold)
       }
       Me.LblHue.BringToFront()

   End Sub

   Private Sub Form1_Shown(ByVal sender As Object, ByVal e As EventArgs) _
   Handles Me.Shown

       Me.SuspendLayout()
       Me.Controls.AddRange({Me.PcbPreview, Me.BtLoad, Me.BtSave, Me.TrckHue, Me.LblHue})
       Me.ResumeLayout()

   End Sub

   Private Sub BtLoad_Click(ByVal sender As Object, ByVal e As EventArgs) _
   Handles BtLoad.Click

       Using ofd As New OpenFileDialog()
           ofd.Title = "Open image"
           ofd.Filter = "Image files|*.jpg;*.png;*.bmp"

           If (ofd.ShowDialog() = DialogResult.OK) Then
               If (Me.srcImg IsNot Nothing) Then
                   Me.srcImg.Dispose()
               End If
               Me.srcImg = Image.FromFile(ofd.FileName)

               If (Me.thumbnail IsNot Nothing) Then
                   Me.thumbnail.Dispose()
               End If
               Dim thumbSize As Size = Me.PcbPreview.Size
               Me.thumbnail = Me.srcImg.GetThumbnailImage(thumbSize.Width, thumbSize.Heigth, Nothing, Nothing)

               ' Force TrackBar.OnValueChanged event to trigger.
               Me.TrckHue.Value = 1
               Me.TrckHue.Value = 0

           End If
       End Using ' ofd

   End Sub

   Private Sub BtSave_Click(ByVal sender As Object, ByVal e As EventArgs) _
   Handles BtSave.Click


       Using sfd As New SaveFileDialog()
           sfd.Title = "Save image"
           sfd.Filter = "Bitmap image|*.bmp|Jpeg image|*.jpg|PNG image|*.png"
           sfd.AddExtension = True

           If (sfd.ShowDialog() = DialogResult.OK) Then
               Dim file As New FileInfo(sfd.FileName)
               Dim ext As String = file.Extension.ToLower()
               Dim format As ImageFormat

               Select Case ext
                   Case ".png"
                       format = ImageFormat.Png
                   Case ".bmp"
                       format = ImageFormat.Bmp
                   Case Else ' jpg
                       format = ImageFormat.Jpeg
               End Select

               Dim factor As Single = (Me.TrckHue.Value + 100)
               Using img As Image = Me.srcImg.SetImageSaturation(factor, highQuality:=True)
                   img.Save(file.FullName, format)
               End Using ' img

           End If
       End Using ' sfd

   End Sub

   Private Sub TrckHue_ValueChanged(ByVal sender As Object, ByVal e As EventArgs) _
   Handles TrckHue.ValueChanged

       Dim trck As TrackBar = DirectCast(sender, TrackBar)
       Dim value As Integer = trck.Value
       Dim factor As Single = (trck.Value + 100)

       Dim pcbUpdate As Action =
           Sub()
               Me.LblHue.Invoke(Sub()
                                    Me.LblHue.Text = CStr(value)
                                    Me.Update()
                                End Sub)
               Dim lockImg As Image = Me.thumbnail
               SyncLock lockImg
                   lockImg = lockImg.SetImageSaturation(factor, highQuality:=False)
                   Me.PcbPreview.Image = lockImg
               End SyncLock
           End Sub

       Task.Factory.StartNew(pcbUpdate)

   End Sub

End Class


Código (vbnet) [Seleccionar]
Public Module ImageExtensions

   <DebuggerStepThrough>
   <Extension>
   <EditorBrowsable(EditorBrowsableState.Always)>
   Public Function SetImageSaturation(ByVal srcImg As Image, ByVal factor As Single,
                                      ByVal highQuality As Boolean) As Image

       Dim r As Single = (299 * (100 - factor) / 100000.0F)
       Dim g As Single = (587 * (100 - factor) / 100000.0F)
       Dim b As Single = (114 * (100 - factor) / 100000.0F)

       factor = (factor / 100.0F)
       Dim bmp As New Bitmap(srcImg.Width, srcImg.Height, srcImg.PixelFormat)
       Dim matrix As Single()() = {
               New Single() {(r + factor), r, r, 0.0F, 0.0F},
               New Single() {g, (g + factor), g, 0.0F, 0.0F},
               New Single() {b, b, (b + factor), 0.0F, 0.0F},
               New Single() {0.0F, 0.0F, 0.0F, 1.0F, 0.0F},
               New Single() {0.0F, 0.0F, 0.0F, 0.0F, 1.0F}
       } ' Esta matriz de color la ideó el usuario @FJDA con el propósito de saturar una imagen.

       Using ia As New ImageAttributes
           ia.ClearColorMatrix()
           ia.SetColorMatrix(New ColorMatrix(matrix), ColorMatrixFlag.Default, ColorAdjustType.Bitmap)
           ia.SetGamma(1.0F, ColorAdjustType.Bitmap)

           Using gdi As Graphics = Graphics.FromImage(bmp)
               With gdi
                   If highQuality Then
                       .CompositingQuality = CompositingQuality.HighQuality
                       .InterpolationMode = InterpolationMode.HighQualityBicubic
                       .PixelOffsetMode = PixelOffsetMode.HighQuality
                       .SmoothingMode = SmoothingMode.HighQuality

                   Else
                       .CompositingQuality = CompositingQuality.HighSpeed
                       .InterpolationMode = InterpolationMode.NearestNeighbor
                       .PixelOffsetMode = PixelOffsetMode.None
                       .SmoothingMode = SmoothingMode.None

                   End If
                   .DrawImage(srcImg, New Rectangle(0, 0, bmp.Width, bmp.Height),
                                                    0, 0, srcImg.Width, srcImg.Height,
                                                    GraphicsUnit.Pixel, ia)
               End With

           End Using ' gdi
       End Using ' ia

       Return bmp

   End Function

End Module


Como puedes comprobar, al igual que en tu código de ejemplo, yo también utilizo un único método para manipular ambas imágenes, sin embargo lo hago de una forma muy distinta, en base a un factor booleano de calidad gráfica (parámetro highQuality) que es lo que nos ayuda a aumentar el rendimiento produciendo una imagen de baja calidad al generar la imagen de previsualización, y una imagen de máxima calidad al guardar la imagen de tamaño real en el disco.

La extensión de método la extraí de mi API gratuita ElektroKit y posteriormente la adapté a tus necesidades.


En mi librería gratuita ElektroKit puedes encontrar muchas otras utilidades interesantes que te podrían ayudar a manipular imágenes de forma general, y también para ayudarte en otras muchas diversas tareas de la programación cotidiana en .NET que nada tengan que ver con la manipulación de imágenes.

Si quieres conocer un poco más sobre ElektroKit, lee este tema:




Aquí te dejo una demostración visual para que se aprecie la mejora de la modificación que le hice al código que publicaste.

En la demo primero cargo y manipulo una imagen de un tigre, a una resolución de 5184x3456 px. y de 18 mb, y luego una imagen de un cachorro, a 1920x1080 px. y de 3 mb. El único tiempo de espera apreciable sería al cargar y/o guardar la imagen, puesto que para el resto como ya expliqué se manipula una imagen a tamaño redimensionado.

[youtube=640,360]https://www.youtube.com/watch?v=2VxoHrHWoxA[/youtube]

Espero que todo esto te haya servido de algo.

Saludos
#3243
Bueno, como te prometí, vamos al tema...

Desconozco cual es el código original que estarás usando, pero el código de ejemplo que has compartido tiene varios problemas, e imagino que los mismos problemas estarán replicados en el código original...

Por orden de importancia:




Cita de: FJDA en 16 Septiembre 2016, 16:45 PMestoy intentando saturar una imagen
...
el programa tarda mucho en procesar los cambios.
...
no va bien.
...
al usar un TrackBar el proceso de los cambios es demasiado lento.

El problema principal (y el más grave) por el cual se aprecia una elevada lentitud de respuesta al mover el TrackBar, es por que estás manipulando la imagen a tamaño real cada vez que mueves la posición del TrackBar, y eso causa un gran impacto negativo en el rendimiento de la aplicación.

Si tenemos un PictureBox donde quieres previsualizar la imagen, entonces lo primero que debemos hacer para evitar problemas de rendimiento es redimensaionar la imagen original al tamaño de ese PictureBox, eso lo puedes hacer "manualmente" creando un objeto Bitmap del tamaño deseando y dibujando la imagen, o simplemente llamando a la función Image.GetThumbnailImage(), y entonces, manipular la imagen redimensionada.




Cita de: FJDA en 16 Septiembre 2016, 16:45 PMDim Grafico As Graphics
...
Grafico.DrawImage(...)

El segundo problema es que estás utilizando los parámetros por defecto de calidad de imagen al dibujar la imagen modificada y, al tratarse de una previsualización, logicamente deberiamos personalizar esos parámetros para crear una imagen de baja calidad, es decir, más rápida de procesar.

Los parámetros (o propiedades) que debes ajustar son las siguientes:
  • Graphics.CompositingQuality = CompositingQuality.HighSpeed
  • Graphics.InterpolationMode = InterpolationMode.NearestNeighbor
  • Graphics.PixelOffsetMode = PixelOffsetMode.None
  • Graphics.SmoothingMode = SmoothingMode.None




Cita de: FJDA en 16 Septiembre 2016, 16:45 PMDim PictureBox1 As New PictureBox With {...
                                       .SizeMode = PictureBoxSizeMode.StretchImage,
                                       ...}

Si a todo lo anterior le sumamos que cada vez que asignas la imagen modificada a tamaño real, ésta debe ser vuelta a modificar para ser estrechada, esto logicamente disminuirá todavía más el rendimiento ...de hecho el estrechamiento de cualquier imagen es expensivo de por si.

La solución es sencilla y obvia, debemos restaurar el valor por defecto (PictureBoxSizeMode.Normal) para no forzar otra redimensión adicional de la imagen, y en su lugar utilizar una imagen del tamaño del PictureBox, como ya expliqué más arriba.




El último problema (pero no menos importante), es que todo el procedimiento o algoritmo del código que has publicado se lleva a cabo de forma sincrónica, y esto supone que cada vez que mueves el TrackBar, el hilo de la interfáz de usuario debe esperar a que la imagen se procese y la modificación de imagen se genere para poder procesar el siguiente evento de "mover" del TrackBar, y esto se aprecia en forma de desagradables congelamientos de respuesta o "trompicones" al intentar mover el TrackBar demasiado rápido, puesto que se necesita mucho más tiempo para procesar todo lo que haces con esa imagen a tamaño real, que para mover el TrackBar.

Tanto en C#/VB.NET como en cualquier otro lenguaje, a mayor cantidad de datos que procesar (y una imagen cotidiana contiene muchos datos que procesar) necesitará mayor tiempo de procesado, y hay que esperar ese tiempo, es así de simple. Dicho de otro modo: estás saturando el hilo de la interfáz de usuario.




También cabe mencionar que no estás haciendo un buen uso, o mejor dicho directamente no haces ningún uso de la correcta administración del Garbage Collector para ayudarle a recolectar los recursos de los objetos que ya no sean necesarios por tu aplicación.

Debes asegurarte siempre, sin excepción, de liberar los objetos que sean deshechables llamando al método Object.Dispose(), incluso con los objetos que se liberen automáticamente al liberar un Form, no pierdas la costumbre.

Esto no afecta en el rendimiento de la interfáz de usuario (al menos no en el código de ejemplo que has publicado), pero si que afectará al consumo de memoria, y mucho. Literalmente hablando hay una fuga muy grave de memoria en el código que has publicado, basta con cargar una imagen de varios megabytes (+/-10 mb) y mover la posición del trackbar un par de veces para ver como el espacio reservado va subiendo, y subiendo, y subiendo... y nunca baja, puesto que nunca liberas los recursos no-administrados (Win32) de las imágenes llamando al método Dispose.




Cita de: FJDA en 16 Septiembre 2016, 21:06 PMIntenté usar funciones que PictureBox tiene en C# que simplifican mucho todo pero no están disponibles en VB

No se a que te estarás refiriendo pero eso no es así.

C# y VB.NET son dos lenguajes que trabajan bajo el mismo framework de Microsoft, por ende, ambos pueden utilizar todas las funciones que estén definidas en la librería de clases de .NET Framework. Ambos lenguajes son idénticos en esencia, excepto algunas peculiaridades muy concretas de cada lenguaje.
#3244
lo estás complicando todo demasiado.

en un rato despues de cenar editaré este mensaje para mostrarte una solución completa y funcional (sin ningún tipo de "retraso" o "bloqueo") e indicarte (algunos de) los fallos del código actual que tienes.

hasta ahora!
#3245
Si no proporcionas más información no creo que te podamos ayudar por que no hay ningún código que poder analizar para verificar donde está el fallo.




Cita de: TrashAmbishion en 16 Septiembre 2016, 04:44 AMEl cancela el worker pero no se activa el RunWorkerComplete nunca...

¿Como que no?, por supuesto que si.

Toma esa class que has publicado y testeala de esta forma tan simple:

Código (vbnet) [Seleccionar]
Public Class Form1 : Inherits Form

   Private ReadOnly worker As New BWorkerProc

   Private Sub Button_Start_Click() Handles Button1.Click
       Me.worker.StartBackgroundTask()
   End Sub

   Private Sub Button_Stop_Click() Handles Button2.Click
       Me.worker.Cancel()
   End Sub

End Class


...teniendo así esta parte del código que has publicado:
Código (vbnet) [Seleccionar]
....
Private Sub MyWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles MyWorker.DoWork

   Do Until MyWorker.CancellationPending
       Continue Do
   Loop

   e.Cancel = True

End Sub

Private Sub MyWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) _
Handles myWorker.RunWorkerCompleted

   If e.Cancelled = True Then
       MsgBox("Thread cancelled")
   End If

End Sub
....




Como ves, el evento RunWorkerCompleted se dispara correctamente.






De todas formas, te recomiendo que utilices esta implementación actualizada y optimizada que escribí:

Código (vbnet) [Seleccionar]
#Region " Option Statements "

Option Strict On
Option Explicit On
Option Infer Off

#End Region

#Region " Imports "

Imports System.ComponentModel
Imports System.Diagnostics
Imports System.Threading

#End Region

#Region " BackgroundWorker State "

''' ----------------------------------------------------------------------------------------------------
''' <summary>
''' Specifies the state of a <see cref="BackgroundWorker"/>.
''' </summary>
''' ----------------------------------------------------------------------------------------------------
Public Enum BackgroundWorkerState As Integer

   ''' <summary>
   ''' The <see cref="BackgroundWorker"/> is stopped.
   ''' </summary>
   Stopped = 0

   ''' <summary>
   ''' The <see cref="BackgroundWorker"/> is running.
   ''' </summary>
   Running = 1

   ''' <summary>
   ''' The <see cref="BackgroundWorker"/> is paused.
   ''' </summary>
   Paused = 2

   ''' <summary>
   ''' The <see cref="BackgroundWorker"/> is pending on a cancellation.
   ''' </summary>
   CancellationPending = 3

   ''' <summary>
   ''' The <see cref="BackgroundWorker"/> is completed (stopped).
   ''' </summary>
   Completed = 4

End Enum

#End Region

#Region " My Background Work "

Public NotInheritable Class MyBackgroundWork : Implements IDisposable

#Region " Private Fields "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' The underliying <see cref="BackgroundWorker"/> instance that runs this work on background.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   <EditorBrowsable(EditorBrowsableState.Never)>
   Friend WithEvents Worker As BackgroundWorker

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' A <see cref="ManualResetEvent"/> that serves to handle synchronous operations (Run, Pause, Resume, Cancel).
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private ReadOnly mreSync As ManualResetEvent

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' A <see cref="ManualResetEvent"/> that serves to handle asynchronous operations (RunAsync, CancelAsync).
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private ReadOnly mreAsync As ManualResetEvent

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Indicates whether <see cref="BackGroundworker"/> has been initiated in synchronous mode.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private isRunSync As Boolean = False

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Indicates whether a synchronous cancellation operation is requested.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private isCancelSyncRequested As Boolean = False

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Indicates whether a pause operation is requested.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private isPauseRequested As Boolean = False

#End Region

#Region " Properties "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Gets the current state of the background work.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <value>
   ''' The current state of the background work.
   ''' </value>
   ''' ----------------------------------------------------------------------------------------------------
   Public ReadOnly Property State As BackgroundWorkerState
       <DebuggerStepThrough>
       Get
           Return Me.stateB
       End Get
   End Property
   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' ( Backing Field )
   ''' The current state of the background work.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private stateB As BackgroundWorkerState = BackgroundWorkerState.Stopped

#End Region

#Region " Constructors "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Initializes a new instance of the <see cref="MyBackgroundWork"/> class.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerNonUserCode>
   Public Sub New()

       Me.Worker = New BackgroundWorker()
       Me.mreSync = New ManualResetEvent(initialState:=False)
       Me.mreAsync = New ManualResetEvent(initialState:=True)

   End Sub

#End Region

#Region " Public Methods "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Run the background work.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <exception cref="InvalidOperationException">
   ''' In order to run the BackgroundWorker instance it must be stopped or completed.
   ''' </exception>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Public Sub Run()

       If (Me.Worker Is Nothing) Then
           Throw New ObjectDisposedException(objectName:="Worker")

       Else
           Select Case Me.stateB

               Case BackgroundWorkerState.Stopped, BackgroundWorkerState.Completed
                   Me.isRunSync = True
                   With Me.Worker
                       .WorkerSupportsCancellation = False
                       .WorkerReportsProgress = False
                       .RunWorkerAsync()
                   End With
                   Me.stateB = BackgroundWorkerState.Running
                   Me.mreSync.WaitOne()

               Case Else
                   Throw New InvalidOperationException("In order to run the BackgroundWorker instance it must be stopped or completed.")

           End Select

       End If

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Asynchronouslly run the background work.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <exception cref="InvalidOperationException">
   ''' In order to run the BackgroundWorker instance it must be stopped or completed.
   ''' </exception>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Public Sub RunAsync()

       If (Me.Worker Is Nothing) Then
           Throw New ObjectDisposedException(objectName:="Worker")

       Else
           Select Case Me.stateB

               Case BackgroundWorkerState.Stopped, BackgroundWorkerState.Completed
                   With Me.Worker
                       .WorkerSupportsCancellation = True
                       .WorkerReportsProgress = True
                       .RunWorkerAsync()
                   End With
                   Me.stateB = BackgroundWorkerState.Running

               Case Else
                   Throw New InvalidOperationException("In order to run the BackgroundWorker instance it must be stopped or completed.")

           End Select

       End If

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Asynchronouslly pause the background work.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <exception cref="InvalidOperationException">
   ''' In order to pause the BackgroundWorker instance it must be running.
   ''' </exception>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Public Sub PauseAsync()

       If (Me.Worker Is Nothing) Then
           Throw New ObjectDisposedException(objectName:="Worker")

       Else
           Select Case Me.stateB

               Case BackgroundWorkerState.Running
                   Me.isPauseRequested = True
                   Me.stateB = BackgroundWorkerState.Paused
                   Me.mreAsync.Reset()

               Case Else
                   Throw New InvalidOperationException("In order to pause the BackgroundWorker instance it must be running.")

           End Select

       End If

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Resume the background work.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <exception cref="InvalidOperationException">
   ''' In order to resume the BackgroundWorker instance it must be paused.
   ''' </exception>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Public Sub [Resume]()

       If (Me.Worker Is Nothing) Then
           Throw New ObjectDisposedException(objectName:="Worker")

       Else
           Select Case Me.stateB

               Case BackgroundWorkerState.Paused
                   Me.stateB = BackgroundWorkerState.Running
                   Me.isPauseRequested = False
                   Me.mreAsync.Set()

               Case Else
                   Throw New InvalidOperationException("In order to resume the BackgroundWorker instance must be paused.")

           End Select

       End If

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Cancel the background work.
   ''' <para></para>
   ''' It blocks the caller thread until the remaining work is done.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <exception cref="InvalidOperationException">
   ''' In order to cancel the BackgroundWorker instance it must be running or paused.
   ''' </exception>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Public Sub Cancel()

       Me.isCancelSyncRequested = True
       Me.CancelAsync()
       Me.mreSync.WaitOne()
       Me.isCancelSyncRequested = False

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Asynchronouslly cancel the background work.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <exception cref="InvalidOperationException">
   ''' In order to cancel the BackgroundWorker instance it must be running or paused.
   ''' </exception>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Public Sub CancelAsync()

       If (Me.Worker Is Nothing) Then
           Throw New ObjectDisposedException(objectName:="Worker")

       Else
           Select Case Me.stateB

               Case BackgroundWorkerState.CancellationPending
                   Exit Sub

               Case BackgroundWorkerState.Running, BackgroundWorkerState.Paused
                   Me.mreAsync.Set() ' Resume thread if it is paused.
                   Me.stateB = BackgroundWorkerState.CancellationPending
                   Me.Worker.CancelAsync() ' Cancel it.

               Case Else
                   Throw New InvalidOperationException("In order to cancel the BackgroundWorker instance must be running or paused.")

           End Select

       End If

   End Sub

#End Region

#Region " Private Methods "

   <DebuggerStepperBoundary>
   Private Sub DoSomething()
       Thread.Sleep(TimeSpan.FromSeconds(5))
   End Sub

#End Region

#Region " Event-Handlers "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Handles the <see cref="BackgroundWorker.DoWork"/> event of the <see cref="Worker"/> instance.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <param name="sender">
   ''' The source of the event.
   ''' </param>
   '''
   ''' <param name="e">
   ''' The <see cref="DoWorkEventArgs"/> instance containing the event data.
   ''' </param>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepperBoundary>
   Private Sub Worker_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) _
   Handles Worker.DoWork

       Dim progress As Integer

       Dim lock As Object = ""
       SyncLock lock

           For i As Integer = 0 To 100

               If (Me.Worker.CancellationPending) Then
                   e.Cancel = True
                   Exit For

               Else
                   If (Me.isPauseRequested) Then ' Pause this thread right here.
                       Me.mreAsync.WaitOne(Timeout.Infinite)
                   End If

                   Me.DoSomething()

                   If Me.Worker.WorkerReportsProgress Then
                       progress = i
                       Me.Worker.ReportProgress(progress)
                   End If

               End If

           Next i

       End SyncLock

       If (Me.Worker.WorkerReportsProgress) AndAlso Not (Me.Worker.CancellationPending) AndAlso (progress < 100) Then
           Me.Worker.ReportProgress(percentProgress:=100)
       End If

       If (Me.isRunSync) OrElse (Me.isCancelSyncRequested) Then
           Me.mreSync.Set()
       End If

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Handles the <see cref="BackgroundWorker.ProgressChanged"/> event of the <see cref="Worker"/> instance.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <param name="sender">
   ''' The source of the event.
   ''' </param>
   '''
   ''' <param name="e">
   ''' The <see cref="ProgressChangedEventArgs"/> instance containing the event data.
   ''' </param>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepperBoundary>
   Private Sub Worker_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) _
   Handles Worker.ProgressChanged

       Console.WriteLine(String.Format("Work Progress: {0:00.00}%", e.ProgressPercentage))

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Handles the <see cref="BackgroundWorker.RunWorkerCompleted"/> event of the <see cref="Worker"/> instance.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <param name="sender">
   ''' The source of the event.
   ''' </param>
   '''
   ''' <param name="e">
   ''' The <see cref="RunWorkerCompletedEventArgs"/> instance containing the event data.
   ''' </param>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepperBoundary>
   Private Sub Worker_RunWorkerCompleted(ByVal sender As Object, ByVal e As RunWorkerCompletedEventArgs) _
   Handles Worker.RunWorkerCompleted

       If (e.Cancelled) Then
           Console.WriteLine("Background work cancelled.")

       ElseIf (e.Error IsNot Nothing) Then
           Console.WriteLine("Background work error.")

       Else
           Console.WriteLine("Background work done.")

       End If

       Me.stateB = BackgroundWorkerState.Completed

   End Sub

#End Region

#Region " IDisposable Implementation "

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Flag to detect redundant calls when disposing.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   Private isDisposed As Boolean
   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Releases all the resources used by this instance.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Public Sub Dispose() Implements IDisposable.Dispose

       Me.Dispose(isDisposing:=True)
       GC.SuppressFinalize(obj:=Me)

   End Sub

   ''' ----------------------------------------------------------------------------------------------------
   ''' <summary>
   ''' Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
   ''' <para></para>
   ''' Releases unmanaged and, optionally, managed resources.
   ''' </summary>
   ''' ----------------------------------------------------------------------------------------------------
   ''' <param name="isDisposing">
   ''' <see langword="True"/> to release both managed and unmanaged resources;
   ''' <see langword="False"/> to release only unmanaged resources.
   ''' </param>
   ''' ----------------------------------------------------------------------------------------------------
   <DebuggerStepThrough>
   Private Sub Dispose(ByVal isDisposing As Boolean)

       If (Not Me.isDisposed) AndAlso (isDisposing) Then

           If (Me.Worker IsNot Nothing) Then
               Me.Worker.Dispose()
               Me.Worker = Nothing

               With Me.mreSync
                   .SafeWaitHandle.Close()
                   .Dispose()
               End With

               With Me.mreAsync
                   .SafeWaitHandle.Close()
                   .Dispose()
               End With

               Me.isRunSync = False
               Me.stateB = BackgroundWorkerState.Stopped
           End If

       End If

       Me.isDisposed = True

   End Sub

#End Region

End Class

#End Region


Ejemplo de uso:
Código (vbnet) [Seleccionar]
Public Class Form1

   Friend Worker As MyBackgroundWork

   Private Sub Run_Click() Handles Button_Start.Click

       If (Me.Worker IsNot Nothing) Then
           Select Case Me.Worker.State
               Case BackgroundWorkerState.Running, BackgroundWorkerState.Paused
                   Me.Worker.Cancel()
               Case Else
                    Do Nothing.
           End Select
       End If

       Me.Worker = New MyBackgroundWork
       Me.Worker.RunAsync()

   End Sub

   Private Sub Pause_Click() Handles Button_Pause.Click
       Me.Worker.PauseAsync()
   End Sub

   Private Sub Resume_Click() Handles Button_Resume.Click
       Me.Worker.Resume()
   End Sub

   Private Sub Cancel_Click() Handles Button_Cancel.Click
       Me.Worker.CancelAsync()
   End Sub

End Class


Saludos
#3246
Hacking / Re: La Clase
15 Septiembre 2016, 17:38 PM
Este es un foro de hacking ético. Por favor, lee las normas del foro.

Tema Cerrado
#3247
.NET (C#, VB.NET, ASP) / Re: Ayuda: Enumerar ficheros
14 Septiembre 2016, 20:40 PM
Cita de: Tomas1982 en 14 Septiembre 2016, 20:27 PMcomo logro contar la cantidad de fichero por tipo de extensión

Tomando como ejemplo el código que publiqué arriba, puedes hacerlo de la siguiente manera:

Código (vbnet) [Seleccionar]
Dim groups As IEnumerable(Of IGrouping(Of String, FileInfo)) =
   New DirectoryInfo(".\").EnumerateFiles("*", SearchOption.TopDirectoryOnly).
                           GroupBy(Of String)(Function(file As FileInfo) file.Extension)

Dim totalFileCount As Integer =
   groups.Sum(Function(group As IGrouping(Of String, FileInfo)) group.Count) ' Cantidad total de archivos.

For Each group As IGrouping(Of String, FileInfo) In groups
   Dim fileCount As Integer = group.Count ' Cantidad de archivos de este grupo.
   ...
Next group


Saludos!
#3248
Cita de: ill_milk en 14 Septiembre 2016, 18:48 PMAl iniciar windows me aparecen 4 mensajes que rezan lo siguiente: "El programa no puede iniciarse porque falta MSVCP100.dll [ó MSVCR100.dll en los 3 mensajes restantes]
...
he pensado (sustituir los .dll en los directorios que generen el conflicto, desinstalar y volver a instalar Microsoft Visual C++

Los archivos con nombre MSVC*100.dll forman parte de los runtimes de Microsoft Visual C++ 2010, por ende, debes asegurarte de instalar esa versión (adicionalmente a cualquier otra versión que ya tengas instalada).

Aquí los tienes a mano para cualquier ocasión:

Cita de: Elektro

Debes realizar una instalación limpia, es decir, primero de nada desinstalas los paquetes que hayas instalado de Microsoft Visual C++ 2010, reinicias el PC, instalas la versión x86 de esos runtimes, y la x64 en caso de que tengas un Windows de 64 Bits, y por último instalas también los service packs para esa versión, y reinicias de nuevo el PC.

Si con eso no es suficiente para solucionar la aparición de mensajes de errores, entonces puedes probar a copiar los archivos MSVC*100.dll al directorio raíz de las aplicaciones que te muestran el mensaje de error (si el executable es de 32 Bit entonces debes copiar las dll de 32 Bits, si el executable es de 64 Bit, las dll de 64 Bit), de ese modo en teoría sería imposible que te siga indicando que no puede encontrar las librerías, puesto que el sistema operativo primero usa el directorio raíz del executable para localizar los runtimes, y luego el directorio de archivos del sistema, en ese orden.




Cita de: ill_milk en 14 Septiembre 2016, 18:48 PMIntente reinstalar el programa para corregir el problema." No se a que p*** programa se refiere

Es algo sencillo de averiguar, puedes intuir cual puede ser la posible aplicación conflictiva simplemente exminando los programas que se inicien con Windows, para ello puedes utilizar por ejemplo la aplicación AutoRuns de SysInternals:

O bien puedes depurar el error y así determinar de manera inequívoca cual es la aplicación o aplicaciones conflictivas, utilizando el Visor de Eventos de Windows (Event Viewer) que está ubicado en la ruta "C:\Windows\System32\eventvwr.exe". Para llevar a cabo este análisis necesitas unos conocimientos mínimos, y primero te aconsejo que limpies todos los registros de eventos... puesto que tendrás decenas o cientos de miles de entradas acumuladas, y luego resultaria una tarea muy tediosa ponerte a buscar entre tantas entradas.

Saludos
#3249
.NET (C#, VB.NET, ASP) / Re: Ayuda: Enumerar ficheros
14 Septiembre 2016, 18:04 PM
Puedes agrupar los archivos por su extensión de archivo utilizando el método Enumerable.GroupBy() de LINQ. Te escribo un ejemplo:

Código (vbnet) [Seleccionar]
Dim groups As IEnumerable(Of IGrouping(Of String, FileInfo)) =
   New DirectoryInfo(".\").EnumerateFiles("*", SearchOption.TopDirectoryOnly).
                           GroupBy(Of String)(Function(file As FileInfo) file.Extension)

For Each group As IGrouping(Of String, FileInfo) In groups

   Dim sb As New StringBuilder(capacity:=(group.Count * 260)) ' Suggested capacity. 260 = MAX_PATH
   With sb
       .AppendFormat("Group of file extension '{0}'", group.Key)
       .AppendLine()
       .AppendLine(String.Join(Environment.NewLine, group))
   End With
   Console.WriteLine(sb.ToString())

Next group


Resultado de ejecución:
Cita de: Visual StudioGroup of file extension: '.exe'
WindowsApplication1.exe
WindowsApplication1.vshost.exe

Group of file extension: '.config'
WindowsApplication1.exe.config
WindowsApplication1.vshost.exe.config

Group of file extension: '.pdb'
WindowsApplication1.pdb

Group of file extension: '.xml'
WindowsApplication1.xml

Saludos!